summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Klos <martin.klos@basyskom.com>2021-01-19 16:53:23 +0100
committerJannis Völker <jannis.voelker@basyskom.com>2022-11-11 12:47:52 +0000
commit6a1a89b485ff373a5710ec73be06ab2039a33572 (patch)
tree505638e54c385df3c632691d1766e1b827cb7a7c
parent50dba29a20474210743131076ce1e32a6593cda6 (diff)
Update open62541 to 1.3
The open62541 plugin now supports the Aes128_Sha256_RsaOaep security policy. MacOS on M1 has been disabled due to issue #5198 in open62541. Change-Id: I8b1cf704a9a0532fa9eb2c9099cac62ac9263a49 Reviewed-by: Frank Meerkoetter <frank.meerkoetter@basyskom.com>
-rw-r--r--coin/module_config.yaml23
-rw-r--r--config.tests/open62541/main.cpp2
-rw-r--r--examples/opcua/waterpump/simulationserver/CMakeLists.txt2
-rw-r--r--examples/opcua/waterpump/simulationserver/simulationserver.cpp46
-rw-r--r--src/3rdparty/open62541/open62541.c59419
-rw-r--r--src/3rdparty/open62541/open62541.h10762
-rw-r--r--src/3rdparty/open62541/patches/0001-feat-plugin-Add-OpenSSL-3.0-support-5349.patch282
-rw-r--r--src/3rdparty/open62541/patches/0001-fix-core-use-of-compound-volatile-operations-depreca.patch91
-rw-r--r--src/opcua/configure.cmake2
-rw-r--r--src/opcua/doc/src/qtopcua.qdoc8
-rw-r--r--src/plugins/opcua/open62541/CMakeLists.txt4
-rw-r--r--src/plugins/opcua/open62541/qopen62541.h2
-rw-r--r--src/plugins/opcua/open62541/qopen62541backend.cpp24
-rw-r--r--src/plugins/opcua/open62541/qopen62541client.cpp1
-rw-r--r--src/plugins/opcua/open62541/qopen62541node.cpp2
-rw-r--r--src/plugins/opcua/open62541/qopen62541subscription.cpp25
-rw-r--r--src/plugins/opcua/open62541/qopen62541valueconverter.cpp68
-rw-r--r--tests/auto/declarative/AbsoluteNodeTest.qml2
-rw-r--r--tests/auto/declarative/DiscoveryTest.qml4
-rw-r--r--tests/auto/declarative/SecurityTest.qml2
-rw-r--r--tests/auto/qopcuaclient/tst_client.cpp14
-rw-r--r--tests/open62541-testserver/CMakeLists.txt3
-rw-r--r--tests/open62541-testserver/testserver.cpp68
23 files changed, 40658 insertions, 30198 deletions
diff --git a/coin/module_config.yaml b/coin/module_config.yaml
index 4b23a90..55b8f56 100644
--- a/coin/module_config.yaml
+++ b/coin/module_config.yaml
@@ -1,8 +1,25 @@
version: 2
accept_configuration:
- condition: property
- property: features
- not_contains_value: Disable
+ condition: and
+ conditions:
+ - condition: property
+ property: features
+ not_contains_value: Disable
+ - condition: and
+ conditions:
+ - condition: or
+ conditions:
+ - condition: property
+ property: target.os
+ not_equals_value: MacOS
+ - condition: and
+ conditions:
+ - condition: property
+ property: target.os
+ equals_value: MacOS
+ - condition: property
+ property: target.arch
+ not_equals_value: ARM64
instructions:
Build:
diff --git a/config.tests/open62541/main.cpp b/config.tests/open62541/main.cpp
index ab5ae0d..e0d4fc9 100644
--- a/config.tests/open62541/main.cpp
+++ b/config.tests/open62541/main.cpp
@@ -26,7 +26,7 @@ int main(int argc, char *argv[])
}
/* Clean up */
- UA_Variant_deleteMembers(&value);
+ UA_Variant_clear(&value);
UA_Client_delete(client); /* Disconnects the client internally */
return status;
}
diff --git a/examples/opcua/waterpump/simulationserver/CMakeLists.txt b/examples/opcua/waterpump/simulationserver/CMakeLists.txt
index f903cb6..c84297c 100644
--- a/examples/opcua/waterpump/simulationserver/CMakeLists.txt
+++ b/examples/opcua/waterpump/simulationserver/CMakeLists.txt
@@ -69,7 +69,7 @@ if (QT_FEATURE_open62541 AND NOT QT_FEATURE_system_open62541)
PROPERTIES LANGUAGE CXX)
set_source_files_properties(${MODULE_SOURCE}/src/3rdparty/open62541/open62541.c
PROPERTIES COMPILE_OPTIONS
- "/Zc:strictStrings-;/permissive;/wd2362")
+ "/Zc:strictStrings-;/permissive;/wd4200")
endif()
endif()
diff --git a/examples/opcua/waterpump/simulationserver/simulationserver.cpp b/examples/opcua/waterpump/simulationserver/simulationserver.cpp
index 7e67c60..cc7850e 100644
--- a/examples/opcua/waterpump/simulationserver/simulationserver.cpp
+++ b/examples/opcua/waterpump/simulationserver/simulationserver.cpp
@@ -34,11 +34,11 @@ DemoServer::~DemoServer()
{
shutdown();
UA_Server_delete(m_server);
- UA_NodeId_deleteMembers(&m_percentFilledTank1Node);
- UA_NodeId_deleteMembers(&m_percentFilledTank2Node);
- UA_NodeId_deleteMembers(&m_tank2TargetPercentNode);
- UA_NodeId_deleteMembers(&m_tank2ValveStateNode);
- UA_NodeId_deleteMembers(&m_machineStateNode);
+ UA_NodeId_clear(&m_percentFilledTank1Node);
+ UA_NodeId_clear(&m_percentFilledTank2Node);
+ UA_NodeId_clear(&m_tank2TargetPercentNode);
+ UA_NodeId_clear(&m_tank2ValveStateNode);
+ UA_NodeId_clear(&m_machineStateNode);
}
bool DemoServer::init()
@@ -96,10 +96,10 @@ UA_NodeId DemoServer::addObject(const QString &parent, const QString &nodeString
nullptr,
&resultNode);
- UA_QualifiedName_deleteMembers(&nodeBrowseName);
- UA_NodeId_deleteMembers(&requestedNodeId);
- UA_NodeId_deleteMembers(&parentNodeId);
- UA_ObjectAttributes_deleteMembers(&oAttr);
+ UA_QualifiedName_clear(&nodeBrowseName);
+ UA_NodeId_clear(&requestedNodeId);
+ UA_NodeId_clear(&parentNodeId);
+ UA_ObjectAttributes_clear(&oAttr);
if (result != UA_STATUSCODE_GOOD) {
qWarning() << "Could not add folder:" << nodeString << " :" << result;
@@ -133,9 +133,9 @@ UA_NodeId DemoServer::addVariable(const UA_NodeId &folder, const QString &variab
nullptr,
&resultId);
- UA_NodeId_deleteMembers(&variableNodeId);
- UA_VariableAttributes_deleteMembers(&attr);
- UA_QualifiedName_deleteMembers(&variableName);
+ UA_NodeId_clear(&variableNodeId);
+ UA_VariableAttributes_clear(&attr);
+ UA_QualifiedName_clear(&variableName);
if (result != UA_STATUSCODE_GOOD) {
qWarning() << "Could not add variable:" << result;
@@ -314,9 +314,9 @@ UA_NodeId DemoServer::addMethod(const UA_NodeId &folder, const QString &variable
0, nullptr,
this, &resultId);
- UA_NodeId_deleteMembers(&methodNodeId);
- UA_MethodAttributes_deleteMembers(&attr);
- UA_QualifiedName_deleteMembers(&methodBrowseName);
+ UA_NodeId_clear(&methodNodeId);
+ UA_MethodAttributes_clear(&attr);
+ UA_QualifiedName_clear(&methodBrowseName);
if (result != UA_STATUSCODE_GOOD) {
qWarning() << "Could not add Method:" << result;
@@ -350,20 +350,20 @@ void DemoServer::launch()
m_machineStateNode = addVariable(machineObject, "ns=2;s=Machine.State", "State", "Machine State", static_cast<quint32>(MachineState::Idle), QOpcUa::Types::UInt32);
UA_NodeId tempId;
tempId = addVariable(machineObject, "ns=2;s=Machine.Designation", "Designation", "Machine Designation", "TankExample", QOpcUa::Types::String);
- UA_NodeId_deleteMembers(&tempId);
+ UA_NodeId_clear(&tempId);
tempId = addMethod(machineObject, "ns=2;s=Machine.Start", "Starts the pump", "Start", "Start Pump", &startPumpMethod);
- UA_NodeId_deleteMembers(&tempId);
+ UA_NodeId_clear(&tempId);
tempId = addMethod(machineObject, "ns=2;s=Machine.Stop", "Stops the pump", "Stop", "Stop Pump", &stopPumpMethod);
- UA_NodeId_deleteMembers(&tempId);
+ UA_NodeId_clear(&tempId);
tempId = addMethod(machineObject, "ns=2;s=Machine.FlushTank2", "Flushes tank 2", "FlushTank2", "Flush Tank 2", &flushTank2Method);
- UA_NodeId_deleteMembers(&tempId);
+ UA_NodeId_clear(&tempId);
tempId = addMethod(machineObject, "ns=2;s=Machine.Reset", "Resets the simulation", "Reset", "Reset Simulation", &resetMethod);
- UA_NodeId_deleteMembers(&tempId);
+ UA_NodeId_clear(&tempId);
- UA_NodeId_deleteMembers(&machineObject);
- UA_NodeId_deleteMembers(&tank1Object);
- UA_NodeId_deleteMembers(&tank2Object);
+ UA_NodeId_clear(&machineObject);
+ UA_NodeId_clear(&tank1Object);
+ UA_NodeId_clear(&tank2Object);
QObject::connect(&m_machineTimer, &QTimer::timeout, [this]() {
diff --git a/src/3rdparty/open62541/open62541.c b/src/3rdparty/open62541/open62541.c
index 9d508ae..c3692d3 100644
--- a/src/3rdparty/open62541/open62541.c
+++ b/src/3rdparty/open62541/open62541.c
@@ -1,10 +1,10 @@
/* THIS IS A SINGLE-FILE DISTRIBUTION CONCATENATED FROM THE OPEN62541 SOURCES
* visit http://open62541.org/ for information about this software
- * Git-Revision: v1.1.2-8-ge941fc23
+ * Git-Revision: v1.3.3
*/
/*
- * Copyright (C) 2014-2018 the contributors as stated in the AUTHORS file
+ * Copyright (C) 2014-2021 the contributors as stated in the AUTHORS file
*
* This file is part of open62541. open62541 is free software: you can
* redistribute it and/or modify it under the terms of the Mozilla Public
@@ -27,7 +27,7 @@
#include "open62541.h"
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/deps/open62541_queue.h" ***********************************/
+/**** amalgamated original file "/deps/open62541_queue.h" ****/
/* $OpenBSD: queue.h,v 1.38 2013/07/03 15:05:21 fgsch Exp $ */
/* $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $ */
@@ -154,9 +154,9 @@ struct { \
/*
* Singly-linked List functions.
*/
-#define SLIST_INIT(head) { \
+#define SLIST_INIT(head) do { \
SLIST_FIRST(head) = SLIST_END(head); \
-}
+} while(0)
#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
(elm)->field.sle_next = (slistelm)->field.sle_next; \
@@ -675,7 +675,7 @@ struct { \
} while (0)
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/deps/pcg_basic.h" ***********************************/
+/**** amalgamated original file "/deps/pcg_basic.h" ****/
/*
* PCG Random Number Generation for C.
@@ -722,7 +722,7 @@ uint32_t pcg32_random_r(pcg32_random_t* rng);
#endif
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/deps/libc_time.h" ***********************************/
+/**** amalgamated original file "/deps/libc_time.h" ****/
struct mytm {
@@ -738,7 +738,7 @@ int __secs_to_tm(long long t, struct mytm *tm);
long long __tm_to_secs(const struct mytm *tm);
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/deps/base64.h" ***********************************/
+/**** amalgamated original file "/deps/base64.h" ****/
#ifndef UA_BASE64_H_
#define UA_BASE64_H_
@@ -772,7 +772,81 @@ _UA_END_DECLS
#endif /* UA_BASE64_H_ */
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/src/ua_util_internal.h" ***********************************/
+/**** amalgamated original file "/src/ua_types_encoding_binary.h" ****/
+
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Copyright 2014-2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
+ * Copyright 2015 (c) Sten Grüner
+ * Copyright 2014, 2017 (c) Florian Palm
+ * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
+ * Copyright 2017 (c) Mark Giraud, Fraunhofer IOSB
+ */
+
+
+
+_UA_BEGIN_DECLS
+
+typedef UA_StatusCode (*UA_exchangeEncodeBuffer)(void *handle, UA_Byte **bufPos,
+ const UA_Byte **bufEnd);
+
+/* Encodes the scalar value described by type in the binary encoding. Encoding
+ * is thread-safe if thread-local variables are enabled. Encoding is also
+ * reentrant and can be safely called from signal handlers or interrupts.
+ *
+ * @param src The value. Must not be NULL.
+ * @param type The value type. Must not be NULL.
+ * @param bufPos Points to a pointer to the current position in the encoding
+ * buffer. Must not be NULL. The pointer is advanced by the number of
+ * encoded bytes, or, if the buffer is exchanged, to the position in the
+ * new buffer.
+ * @param bufEnd Points to a pointer to the end of the encoding buffer (encoding
+ * always stops before *buf_end). Must not be NULL. The pointer is
+ * changed when the buffer is exchanged.
+ * @param exchangeCallback Called when the end of the buffer is reached. This is
+ used to send out a message chunk before continuing with the encoding.
+ Is ignored if NULL.
+ * @param exchangeHandle Custom data passed into the exchangeCallback.
+ * @return Returns a statuscode whether encoding succeeded. */
+UA_StatusCode
+UA_encodeBinaryInternal(const void *src, const UA_DataType *type,
+ UA_Byte **bufPos, const UA_Byte **bufEnd,
+ UA_exchangeEncodeBuffer exchangeCallback,
+ void *exchangeHandle)
+ UA_FUNC_ATTR_WARN_UNUSED_RESULT;
+
+/* Decodes a scalar value described by type from binary encoding. Decoding
+ * is thread-safe if thread-local variables are enabled. Decoding is also
+ * reentrant and can be safely called from signal handlers or interrupts.
+ *
+ * @param src The buffer with the binary encoded value. Must not be NULL.
+ * @param offset The current position in the buffer. Must not be NULL. The value
+ * is advanced as decoding progresses.
+ * @param dst The target value. Must not be NULL. The target is assumed to have
+ * size type->memSize. The value is reset to zero before decoding. If
+ * decoding fails, members are deleted and the value is reset (zeroed)
+ * again.
+ * @param type The value type. Must not be NULL.
+ * @param customTypesSize The number of non-standard datatypes contained in the
+ * customTypes array.
+ * @param customTypes An array of non-standard datatypes (not included in
+ * UA_TYPES). Can be NULL if customTypesSize is zero.
+ * @return Returns a statuscode whether decoding succeeded. */
+UA_StatusCode
+UA_decodeBinaryInternal(const UA_ByteString *src, size_t *offset,
+ void *dst, const UA_DataType *type,
+ const UA_DataTypeArray *customTypes)
+ UA_FUNC_ATTR_WARN_UNUSED_RESULT;
+
+const UA_DataType *
+UA_findDataTypeByBinary(const UA_NodeId *typeId);
+
+_UA_END_DECLS
+
+
+/**** amalgamated original file "/src/ua_util_internal.h" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -785,23 +859,68 @@ _UA_END_DECLS
* Copyright 2015 (c) Chris Iatrou
* Copyright 2015-2016 (c) Oleksiy Vasylyev
* Copyright 2017 (c) Stefan Profanter, fortiss GmbH
+ * Copyright 2021 (c) Fraunhofer IOSB (Author: Jan Hermes)
*/
#define UA_INTERNAL
+
_UA_BEGIN_DECLS
/* Macro-Expand for MSVC workarounds */
#define UA_MACRO_EXPAND(x) x
/* Print a NodeId in logs */
-#define UA_LOG_NODEID_WRAP(NODEID, LOG) { \
- UA_String nodeIdStr = UA_STRING_NULL; \
- UA_NodeId_print(NODEID, &nodeIdStr); \
- LOG; \
- UA_String_clear(&nodeIdStr); \
-}
+#define UA_LOG_NODEID_INTERNAL(NODEID, LOG) \
+ do { \
+ UA_String nodeIdStr = UA_STRING_NULL; \
+ UA_NodeId_print(NODEID, &nodeIdStr); \
+ LOG; \
+ UA_String_clear(&nodeIdStr); \
+ } while(0)
+
+#if UA_LOGLEVEL <= 100
+# define UA_LOG_NODEID_TRACE(NODEID, LOG) \
+ UA_LOG_NODEID_INTERNAL(NODEID, LOG)
+#else
+# define UA_LOG_NODEID_TRACE(NODEID, LOG)
+#endif
+
+#if UA_LOGLEVEL <= 200
+# define UA_LOG_NODEID_DEBUG(NODEID, LOG) \
+ UA_LOG_NODEID_INTERNAL(NODEID, LOG)
+#else
+# define UA_LOG_NODEID_DEBUG(NODEID, LOG)
+#endif
+
+#if UA_LOGLEVEL <= 300
+# define UA_LOG_NODEID_INFO(NODEID, LOG) \
+ UA_LOG_NODEID_INTERNAL(NODEID, LOG)
+#else
+# define UA_LOG_NODEID_INFO(NODEID, LOG)
+#endif
+
+#if UA_LOGLEVEL <= 400
+# define UA_LOG_NODEID_WARNING(NODEID, LOG) \
+ UA_LOG_NODEID_INTERNAL(NODEID, LOG)
+#else
+# define UA_LOG_NODEID_WARNING(NODEID, LOG)
+#endif
+
+#if UA_LOGLEVEL <= 500
+# define UA_LOG_NODEID_ERROR(NODEID, LOG) \
+ UA_LOG_NODEID_INTERNAL(NODEID, LOG)
+#else
+# define UA_LOG_NODEID_ERROR(NODEID, LOG)
+#endif
+
+#if UA_LOGLEVEL <= 600
+# define UA_LOG_NODEID_FATAL(NODEID, LOG) \
+ UA_LOG_NODEID_INTERNAL(NODEID, LOG)
+#else
+# define UA_LOG_NODEID_FATAL(NODEID, LOG)
+#endif
/* Short names for integer. These are not exposed on the public API, since many
* user-applications make the same definitions in their headers. */
@@ -816,9 +935,122 @@ typedef UA_Int64 i64;
typedef UA_StatusCode status;
/**
+ * Error checking macros
+ */
+
+static UA_INLINE UA_Boolean
+isGood(UA_StatusCode code) {
+ return code == UA_STATUSCODE_GOOD;
+}
+
+static UA_INLINE UA_Boolean
+isNonNull(const void *ptr) {
+ return ptr != NULL;
+}
+
+static UA_INLINE UA_Boolean
+isTrue(uint8_t expr) {
+ return expr;
+}
+
+#define UA_CHECK(A, EVAL_ON_ERROR) \
+ do { \
+ if(UA_UNLIKELY(!isTrue(A))) { \
+ EVAL_ON_ERROR; \
+ } \
+ } while(0)
+
+#define UA_CHECK_STATUS(STATUSCODE, EVAL_ON_ERROR) \
+ UA_CHECK(isGood(STATUSCODE), EVAL_ON_ERROR)
+
+#define UA_CHECK_MEM(STATUSCODE, EVAL_ON_ERROR) \
+ UA_CHECK(isNonNull(STATUSCODE), EVAL_ON_ERROR)
+
+#ifdef UA_DEBUG_FILE_LINE_INFO
+#define UA_CHECK_LOG_INTERNAL(A, STATUSCODE, EVAL, LOG, LOGGER, CAT, MSG, ...) \
+ UA_MACRO_EXPAND( \
+ UA_CHECK(A, LOG(LOGGER, CAT, "" MSG "%s (%s:%d: statuscode: %s)", __VA_ARGS__, \
+ __FILE__, __LINE__, UA_StatusCode_name(STATUSCODE)); \
+ EVAL))
+#else
+#define UA_CHECK_LOG_INTERNAL(A, STATUSCODE, EVAL, LOG, LOGGER, CAT, MSG, ...) \
+ UA_MACRO_EXPAND( \
+ UA_CHECK(A, LOG(LOGGER, CAT, "" MSG "%s (statuscode: %s)", __VA_ARGS__, \
+ UA_StatusCode_name(STATUSCODE)); \
+ EVAL))
+#endif
+
+#define UA_CHECK_LOG(A, EVAL, LEVEL, LOGGER, CAT, ...) \
+ UA_MACRO_EXPAND(UA_CHECK_LOG_INTERNAL(A, UA_STATUSCODE_BAD, EVAL, UA_LOG_##LEVEL, \
+ LOGGER, CAT, __VA_ARGS__, ""))
+
+#define UA_CHECK_STATUS_LOG(STATUSCODE, EVAL, LEVEL, LOGGER, CAT, ...) \
+ UA_MACRO_EXPAND(UA_CHECK_LOG_INTERNAL(isGood(STATUSCODE), STATUSCODE, \
+ EVAL, UA_LOG_##LEVEL, LOGGER, CAT, \
+ __VA_ARGS__, ""))
+
+#define UA_CHECK_MEM_LOG(PTR, EVAL, LEVEL, LOGGER, CAT, ...) \
+ UA_MACRO_EXPAND(UA_CHECK_LOG_INTERNAL(isNonNull(PTR), UA_STATUSCODE_BADOUTOFMEMORY, \
+ EVAL, UA_LOG_##LEVEL, LOGGER, CAT, \
+ __VA_ARGS__, ""))
+
+/**
+ * Check Macros
+ * Usage examples:
+ *
+ * void *data = malloc(...);
+ * UA_CHECK(data, return error);
+ *
+ * UA_StatusCode rv = some_func(...);
+ * UA_CHECK_STATUS(rv, return rv);
+ *
+ * UA_Logger *logger = &server->config.logger;
+ * rv = bar_func(...);
+ * UA_CHECK_STATUS_WARN(rv, return rv, logger, UA_LOGCATEGORY_SERVER, "msg & args %s", "arg");
+ */
+#define UA_CHECK_FATAL(A, EVAL, LOGGER, CAT, ...) \
+ UA_MACRO_EXPAND(UA_CHECK_LOG(A, EVAL, FATAL, LOGGER, CAT, __VA_ARGS__))
+#define UA_CHECK_ERROR(A, EVAL, LOGGER, CAT, ...) \
+ UA_MACRO_EXPAND(UA_CHECK_LOG(A, EVAL, ERROR, LOGGER, CAT, __VA_ARGS__))
+#define UA_CHECK_WARN(A, EVAL, LOGGER, CAT, ...) \
+ UA_MACRO_EXPAND(UA_CHECK_LOG(A, EVAL, WARNING, LOGGER, CAT, __VA_ARGS__))
+#define UA_CHECK_INFO(A, EVAL, LOGGER, CAT, ...) \
+ UA_MACRO_EXPAND(UA_CHECK_LOG(A, EVAL, INFO, LOGGER, CAT, __VA_ARGS__))
+
+#define UA_CHECK_STATUS_FATAL(STATUSCODE, EVAL, LOGGER, CAT, ...) \
+ UA_MACRO_EXPAND( \
+ UA_CHECK_STATUS_LOG(STATUSCODE, EVAL, FATAL, LOGGER, CAT, __VA_ARGS__))
+#define UA_CHECK_STATUS_ERROR(STATUSCODE, EVAL, LOGGER, CAT, ...) \
+ UA_MACRO_EXPAND( \
+ UA_CHECK_STATUS_LOG(STATUSCODE, EVAL, ERROR, LOGGER, CAT, __VA_ARGS__))
+#define UA_CHECK_STATUS_WARN(STATUSCODE, EVAL, LOGGER, CAT, ...) \
+ UA_MACRO_EXPAND( \
+ UA_CHECK_STATUS_LOG(STATUSCODE, EVAL, WARNING, LOGGER, CAT, __VA_ARGS__))
+#define UA_CHECK_STATUS_INFO(STATUSCODE, EVAL, LOGGER, CAT, ...) \
+ UA_MACRO_EXPAND( \
+ UA_CHECK_STATUS_LOG(STATUSCODE, EVAL, INFO, LOGGER, CAT, __VA_ARGS__))
+
+#define UA_CHECK_MEM_FATAL(PTR, EVAL, LOGGER, CAT, ...) \
+ UA_MACRO_EXPAND( \
+ UA_CHECK_MEM_LOG(PTR, EVAL, FATAL, LOGGER, CAT, __VA_ARGS__))
+#define UA_CHECK_MEM_ERROR(PTR, EVAL, LOGGER, CAT, ...) \
+ UA_MACRO_EXPAND( \
+ UA_CHECK_MEM_LOG(PTR, EVAL, ERROR, LOGGER, CAT, __VA_ARGS__))
+#define UA_CHECK_MEM_WARN(PTR, EVAL, LOGGER, CAT, ...) \
+ UA_MACRO_EXPAND( \
+ UA_CHECK_MEM_LOG(PTR, EVAL, WARNING, LOGGER, CAT, __VA_ARGS__))
+#define UA_CHECK_MEM_INFO(PTR, EVAL, LOGGER, CAT, ...) \
+ UA_MACRO_EXPAND( \
+ UA_CHECK_MEM_LOG(PTR, EVAL, INFO, LOGGER, CAT, __VA_ARGS__))
+
+/**
* Utility Functions
* ----------------- */
+const UA_DataType *
+UA_findDataTypeWithCustom(const UA_NodeId *typeId,
+ const UA_DataTypeArray *customTypes);
+
/* Get the number of optional fields contained in an structure type */
size_t UA_EXPORT
getCountOfOptionalFields(const UA_DataType *type);
@@ -924,3022 +1156,73 @@ typedef union {
#endif
} UA_Response;
-_UA_END_DECLS
-
-
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/src/ua_types_encoding_binary.h" ***********************************/
-
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- *
- * Copyright 2014-2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
- * Copyright 2015 (c) Sten Grüner
- * Copyright 2014, 2017 (c) Florian Palm
- * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
- * Copyright 2017 (c) Mark Giraud, Fraunhofer IOSB
- */
-
-
-
-_UA_BEGIN_DECLS
-
-typedef UA_StatusCode (*UA_exchangeEncodeBuffer)(void *handle, UA_Byte **bufPos,
- const UA_Byte **bufEnd);
-
-/* Encodes the scalar value described by type in the binary encoding. Encoding
- * is thread-safe if thread-local variables are enabled. Encoding is also
- * reentrant and can be safely called from signal handlers or interrupts.
- *
- * @param src The value. Must not be NULL.
- * @param type The value type. Must not be NULL.
- * @param bufPos Points to a pointer to the current position in the encoding
- * buffer. Must not be NULL. The pointer is advanced by the number of
- * encoded bytes, or, if the buffer is exchanged, to the position in the
- * new buffer.
- * @param bufEnd Points to a pointer to the end of the encoding buffer (encoding
- * always stops before *buf_end). Must not be NULL. The pointer is
- * changed when the buffer is exchanged.
- * @param exchangeCallback Called when the end of the buffer is reached. This is
- used to send out a message chunk before continuing with the encoding.
- Is ignored if NULL.
- * @param exchangeHandle Custom data passed into the exchangeCallback.
- * @return Returns a statuscode whether encoding succeeded. */
-UA_StatusCode
-UA_encodeBinary(const void *src, const UA_DataType *type,
- UA_Byte **bufPos, const UA_Byte **bufEnd,
- UA_exchangeEncodeBuffer exchangeCallback,
- void *exchangeHandle) UA_FUNC_ATTR_WARN_UNUSED_RESULT;
-
-/* Decodes a scalar value described by type from binary encoding. Decoding
- * is thread-safe if thread-local variables are enabled. Decoding is also
- * reentrant and can be safely called from signal handlers or interrupts.
- *
- * @param src The buffer with the binary encoded value. Must not be NULL.
- * @param offset The current position in the buffer. Must not be NULL. The value
- * is advanced as decoding progresses.
- * @param dst The target value. Must not be NULL. The target is assumed to have
- * size type->memSize. The value is reset to zero before decoding. If
- * decoding fails, members are deleted and the value is reset (zeroed)
- * again.
- * @param type The value type. Must not be NULL.
- * @param customTypesSize The number of non-standard datatypes contained in the
- * customTypes array.
- * @param customTypes An array of non-standard datatypes (not included in
- * UA_TYPES). Can be NULL if customTypesSize is zero.
- * @return Returns a statuscode whether decoding succeeded. */
-UA_StatusCode
-UA_decodeBinary(const UA_ByteString *src, size_t *offset, void *dst,
- const UA_DataType *type, const UA_DataTypeArray *customTypes)
- UA_FUNC_ATTR_WARN_UNUSED_RESULT;
+/* Do not expose UA_String_equal_ignorecase to public API as it currently only handles
+ * ASCII strings, and not UTF8! */
+UA_Boolean UA_EXPORT
+UA_String_equal_ignorecase(const UA_String *s1, const UA_String *s2);
-/* Returns the number of bytes the value p takes in binary encoding. Returns
- * zero if an error occurs. UA_calcSizeBinary is thread-safe and reentrant since
- * it does not access global (thread-local) variables. */
-size_t
-UA_calcSizeBinary(const void *p, const UA_DataType *type);
+/********************/
+/* Encoding Helpers */
+/********************/
-const UA_DataType *
-UA_findDataTypeByBinary(const UA_NodeId *typeId);
+#define UA_ENCODING_HELPERS(TYPE, UPCASE_TYPE) \
+ static UA_INLINE size_t \
+ UA_##TYPE##_calcSizeBinary(const UA_##TYPE *src) { \
+ return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_##UPCASE_TYPE]); \
+ } \
+ static UA_INLINE UA_StatusCode \
+ UA_##TYPE##_encodeBinary(const UA_##TYPE *src, UA_Byte **bufPos, const UA_Byte *bufEnd) { \
+ return UA_encodeBinaryInternal(src, &UA_TYPES[UA_TYPES_##UPCASE_TYPE], \
+ bufPos, &bufEnd, NULL, NULL); \
+ } \
+ static UA_INLINE UA_StatusCode \
+ UA_##TYPE##_decodeBinary(const UA_ByteString *src, size_t *offset, UA_##TYPE *dst) { \
+ return UA_decodeBinaryInternal(src, offset, dst, \
+ &UA_TYPES[UA_TYPES_##UPCASE_TYPE], NULL); \
+ }
+
+UA_ENCODING_HELPERS(Boolean, BOOLEAN)
+UA_ENCODING_HELPERS(SByte, SBYTE)
+UA_ENCODING_HELPERS(Byte, BYTE)
+UA_ENCODING_HELPERS(Int16, INT16)
+UA_ENCODING_HELPERS(UInt16, UINT16)
+UA_ENCODING_HELPERS(Int32, INT32)
+UA_ENCODING_HELPERS(UInt32, UINT32)
+UA_ENCODING_HELPERS(Int64, INT64)
+UA_ENCODING_HELPERS(UInt64, UINT64)
+UA_ENCODING_HELPERS(Float, FLOAT)
+UA_ENCODING_HELPERS(Double, DOUBLE)
+UA_ENCODING_HELPERS(String, STRING)
+UA_ENCODING_HELPERS(DateTime, DATETIME)
+UA_ENCODING_HELPERS(Guid, GUID)
+UA_ENCODING_HELPERS(ByteString, BYTESTRING)
+UA_ENCODING_HELPERS(XmlElement, XMLELEMENT)
+UA_ENCODING_HELPERS(NodeId, NODEID)
+UA_ENCODING_HELPERS(ExpandedNodeId, EXPANDEDNODEID)
+UA_ENCODING_HELPERS(StatusCode, STATUSCODE)
+UA_ENCODING_HELPERS(QualifiedName, QUALIFIEDNAME)
+UA_ENCODING_HELPERS(LocalizedText, LOCALIZEDTEXT)
+UA_ENCODING_HELPERS(ExtensionObject, EXTENSIONOBJECT)
+UA_ENCODING_HELPERS(DataValue, DATAVALUE)
+UA_ENCODING_HELPERS(Variant, VARIANT)
+UA_ENCODING_HELPERS(DiagnosticInfo, DIAGNOSTICINFO)
_UA_END_DECLS
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/build/src_generated/open62541/types_generated_encoding_binary.h" ***********************************/
+/**** amalgamated original file "/build/src_generated/open62541/transport_generated.h" ****/
-/* Generated from Opc.Ua.Types.bsd with script /home/pdie/sonstiges/qtopcua/repos/open62541/tools/generate_datatypes.py
- * on host mintaka by user pdie at 2021-06-21 11:34:37 */
+/**********************************
+ * Autogenerated -- do not modify *
+ **********************************/
#ifdef UA_ENABLE_AMALGAMATION
#else
-#endif
-
-
-
-/* Boolean */
-static UA_INLINE size_t
-UA_Boolean_calcSizeBinary(const UA_Boolean *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_BOOLEAN]);
-}
-static UA_INLINE UA_StatusCode
-UA_Boolean_encodeBinary(const UA_Boolean *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_BOOLEAN], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_Boolean_decodeBinary(const UA_ByteString *src, size_t *offset, UA_Boolean *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_BOOLEAN], NULL);
-}
-
-/* SByte */
-static UA_INLINE size_t
-UA_SByte_calcSizeBinary(const UA_SByte *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_SBYTE]);
-}
-static UA_INLINE UA_StatusCode
-UA_SByte_encodeBinary(const UA_SByte *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_SBYTE], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_SByte_decodeBinary(const UA_ByteString *src, size_t *offset, UA_SByte *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_SBYTE], NULL);
-}
-
-/* Byte */
-static UA_INLINE size_t
-UA_Byte_calcSizeBinary(const UA_Byte *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_BYTE]);
-}
-static UA_INLINE UA_StatusCode
-UA_Byte_encodeBinary(const UA_Byte *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_BYTE], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_Byte_decodeBinary(const UA_ByteString *src, size_t *offset, UA_Byte *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_BYTE], NULL);
-}
-
-/* Int16 */
-static UA_INLINE size_t
-UA_Int16_calcSizeBinary(const UA_Int16 *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_INT16]);
-}
-static UA_INLINE UA_StatusCode
-UA_Int16_encodeBinary(const UA_Int16 *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_INT16], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_Int16_decodeBinary(const UA_ByteString *src, size_t *offset, UA_Int16 *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_INT16], NULL);
-}
-
-/* UInt16 */
-static UA_INLINE size_t
-UA_UInt16_calcSizeBinary(const UA_UInt16 *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_UINT16]);
-}
-static UA_INLINE UA_StatusCode
-UA_UInt16_encodeBinary(const UA_UInt16 *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_UINT16], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_UInt16_decodeBinary(const UA_ByteString *src, size_t *offset, UA_UInt16 *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_UINT16], NULL);
-}
-
-/* Int32 */
-static UA_INLINE size_t
-UA_Int32_calcSizeBinary(const UA_Int32 *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_INT32]);
-}
-static UA_INLINE UA_StatusCode
-UA_Int32_encodeBinary(const UA_Int32 *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_INT32], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_Int32_decodeBinary(const UA_ByteString *src, size_t *offset, UA_Int32 *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_INT32], NULL);
-}
-
-/* UInt32 */
-static UA_INLINE size_t
-UA_UInt32_calcSizeBinary(const UA_UInt32 *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_UINT32]);
-}
-static UA_INLINE UA_StatusCode
-UA_UInt32_encodeBinary(const UA_UInt32 *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_UINT32], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_UInt32_decodeBinary(const UA_ByteString *src, size_t *offset, UA_UInt32 *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_UINT32], NULL);
-}
-
-/* Int64 */
-static UA_INLINE size_t
-UA_Int64_calcSizeBinary(const UA_Int64 *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_INT64]);
-}
-static UA_INLINE UA_StatusCode
-UA_Int64_encodeBinary(const UA_Int64 *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_INT64], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_Int64_decodeBinary(const UA_ByteString *src, size_t *offset, UA_Int64 *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_INT64], NULL);
-}
-
-/* UInt64 */
-static UA_INLINE size_t
-UA_UInt64_calcSizeBinary(const UA_UInt64 *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_UINT64]);
-}
-static UA_INLINE UA_StatusCode
-UA_UInt64_encodeBinary(const UA_UInt64 *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_UINT64], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_UInt64_decodeBinary(const UA_ByteString *src, size_t *offset, UA_UInt64 *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_UINT64], NULL);
-}
-
-/* Float */
-static UA_INLINE size_t
-UA_Float_calcSizeBinary(const UA_Float *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_FLOAT]);
-}
-static UA_INLINE UA_StatusCode
-UA_Float_encodeBinary(const UA_Float *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_FLOAT], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_Float_decodeBinary(const UA_ByteString *src, size_t *offset, UA_Float *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_FLOAT], NULL);
-}
-
-/* Double */
-static UA_INLINE size_t
-UA_Double_calcSizeBinary(const UA_Double *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_DOUBLE]);
-}
-static UA_INLINE UA_StatusCode
-UA_Double_encodeBinary(const UA_Double *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_DOUBLE], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_Double_decodeBinary(const UA_ByteString *src, size_t *offset, UA_Double *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_DOUBLE], NULL);
-}
-
-/* String */
-static UA_INLINE size_t
-UA_String_calcSizeBinary(const UA_String *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_STRING]);
-}
-static UA_INLINE UA_StatusCode
-UA_String_encodeBinary(const UA_String *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_STRING], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_String_decodeBinary(const UA_ByteString *src, size_t *offset, UA_String *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_STRING], NULL);
-}
-
-/* DateTime */
-static UA_INLINE size_t
-UA_DateTime_calcSizeBinary(const UA_DateTime *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_DATETIME]);
-}
-static UA_INLINE UA_StatusCode
-UA_DateTime_encodeBinary(const UA_DateTime *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_DATETIME], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_DateTime_decodeBinary(const UA_ByteString *src, size_t *offset, UA_DateTime *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_DATETIME], NULL);
-}
-
-/* Guid */
-static UA_INLINE size_t
-UA_Guid_calcSizeBinary(const UA_Guid *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_GUID]);
-}
-static UA_INLINE UA_StatusCode
-UA_Guid_encodeBinary(const UA_Guid *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_GUID], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_Guid_decodeBinary(const UA_ByteString *src, size_t *offset, UA_Guid *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_GUID], NULL);
-}
-
-/* ByteString */
-static UA_INLINE size_t
-UA_ByteString_calcSizeBinary(const UA_ByteString *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_BYTESTRING]);
-}
-static UA_INLINE UA_StatusCode
-UA_ByteString_encodeBinary(const UA_ByteString *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_BYTESTRING], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_ByteString_decodeBinary(const UA_ByteString *src, size_t *offset, UA_ByteString *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_BYTESTRING], NULL);
-}
-
-/* XmlElement */
-static UA_INLINE size_t
-UA_XmlElement_calcSizeBinary(const UA_XmlElement *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_XMLELEMENT]);
-}
-static UA_INLINE UA_StatusCode
-UA_XmlElement_encodeBinary(const UA_XmlElement *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_XMLELEMENT], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_XmlElement_decodeBinary(const UA_ByteString *src, size_t *offset, UA_XmlElement *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_XMLELEMENT], NULL);
-}
-
-/* NodeId */
-static UA_INLINE size_t
-UA_NodeId_calcSizeBinary(const UA_NodeId *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_NODEID]);
-}
-static UA_INLINE UA_StatusCode
-UA_NodeId_encodeBinary(const UA_NodeId *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_NODEID], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_NodeId_decodeBinary(const UA_ByteString *src, size_t *offset, UA_NodeId *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_NODEID], NULL);
-}
-
-/* ExpandedNodeId */
-static UA_INLINE size_t
-UA_ExpandedNodeId_calcSizeBinary(const UA_ExpandedNodeId *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_EXPANDEDNODEID]);
-}
-static UA_INLINE UA_StatusCode
-UA_ExpandedNodeId_encodeBinary(const UA_ExpandedNodeId *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_EXPANDEDNODEID], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_ExpandedNodeId_decodeBinary(const UA_ByteString *src, size_t *offset, UA_ExpandedNodeId *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_EXPANDEDNODEID], NULL);
-}
-
-/* StatusCode */
-static UA_INLINE size_t
-UA_StatusCode_calcSizeBinary(const UA_StatusCode *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_STATUSCODE]);
-}
-static UA_INLINE UA_StatusCode
-UA_StatusCode_encodeBinary(const UA_StatusCode *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_STATUSCODE], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_StatusCode_decodeBinary(const UA_ByteString *src, size_t *offset, UA_StatusCode *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_STATUSCODE], NULL);
-}
-
-/* QualifiedName */
-static UA_INLINE size_t
-UA_QualifiedName_calcSizeBinary(const UA_QualifiedName *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_QUALIFIEDNAME]);
-}
-static UA_INLINE UA_StatusCode
-UA_QualifiedName_encodeBinary(const UA_QualifiedName *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_QUALIFIEDNAME], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_QualifiedName_decodeBinary(const UA_ByteString *src, size_t *offset, UA_QualifiedName *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_QUALIFIEDNAME], NULL);
-}
-
-/* LocalizedText */
-static UA_INLINE size_t
-UA_LocalizedText_calcSizeBinary(const UA_LocalizedText *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]);
-}
-static UA_INLINE UA_StatusCode
-UA_LocalizedText_encodeBinary(const UA_LocalizedText *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_LocalizedText_decodeBinary(const UA_ByteString *src, size_t *offset, UA_LocalizedText *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], NULL);
-}
-
-/* ExtensionObject */
-static UA_INLINE size_t
-UA_ExtensionObject_calcSizeBinary(const UA_ExtensionObject *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_EXTENSIONOBJECT]);
-}
-static UA_INLINE UA_StatusCode
-UA_ExtensionObject_encodeBinary(const UA_ExtensionObject *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_ExtensionObject_decodeBinary(const UA_ByteString *src, size_t *offset, UA_ExtensionObject *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], NULL);
-}
-
-/* DataValue */
-static UA_INLINE size_t
-UA_DataValue_calcSizeBinary(const UA_DataValue *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_DATAVALUE]);
-}
-static UA_INLINE UA_StatusCode
-UA_DataValue_encodeBinary(const UA_DataValue *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_DATAVALUE], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_DataValue_decodeBinary(const UA_ByteString *src, size_t *offset, UA_DataValue *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_DATAVALUE], NULL);
-}
-
-/* Variant */
-static UA_INLINE size_t
-UA_Variant_calcSizeBinary(const UA_Variant *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_VARIANT]);
-}
-static UA_INLINE UA_StatusCode
-UA_Variant_encodeBinary(const UA_Variant *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_VARIANT], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_Variant_decodeBinary(const UA_ByteString *src, size_t *offset, UA_Variant *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_VARIANT], NULL);
-}
-
-/* DiagnosticInfo */
-static UA_INLINE size_t
-UA_DiagnosticInfo_calcSizeBinary(const UA_DiagnosticInfo *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_DIAGNOSTICINFO]);
-}
-static UA_INLINE UA_StatusCode
-UA_DiagnosticInfo_encodeBinary(const UA_DiagnosticInfo *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_DiagnosticInfo_decodeBinary(const UA_ByteString *src, size_t *offset, UA_DiagnosticInfo *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], NULL);
-}
-
-/* NodeClass */
-static UA_INLINE size_t
-UA_NodeClass_calcSizeBinary(const UA_NodeClass *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_NODECLASS]);
-}
-static UA_INLINE UA_StatusCode
-UA_NodeClass_encodeBinary(const UA_NodeClass *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_NODECLASS], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_NodeClass_decodeBinary(const UA_ByteString *src, size_t *offset, UA_NodeClass *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_NODECLASS], NULL);
-}
-
-/* StructureType */
-static UA_INLINE size_t
-UA_StructureType_calcSizeBinary(const UA_StructureType *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_STRUCTURETYPE]);
-}
-static UA_INLINE UA_StatusCode
-UA_StructureType_encodeBinary(const UA_StructureType *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_STRUCTURETYPE], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_StructureType_decodeBinary(const UA_ByteString *src, size_t *offset, UA_StructureType *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_STRUCTURETYPE], NULL);
-}
-
-/* StructureField */
-static UA_INLINE size_t
-UA_StructureField_calcSizeBinary(const UA_StructureField *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_STRUCTUREFIELD]);
-}
-static UA_INLINE UA_StatusCode
-UA_StructureField_encodeBinary(const UA_StructureField *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_STRUCTUREFIELD], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_StructureField_decodeBinary(const UA_ByteString *src, size_t *offset, UA_StructureField *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_STRUCTUREFIELD], NULL);
-}
-
-/* StructureDefinition */
-static UA_INLINE size_t
-UA_StructureDefinition_calcSizeBinary(const UA_StructureDefinition *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_STRUCTUREDEFINITION]);
-}
-static UA_INLINE UA_StatusCode
-UA_StructureDefinition_encodeBinary(const UA_StructureDefinition *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_STRUCTUREDEFINITION], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_StructureDefinition_decodeBinary(const UA_ByteString *src, size_t *offset, UA_StructureDefinition *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_STRUCTUREDEFINITION], NULL);
-}
-
-/* Argument */
-static UA_INLINE size_t
-UA_Argument_calcSizeBinary(const UA_Argument *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_ARGUMENT]);
-}
-static UA_INLINE UA_StatusCode
-UA_Argument_encodeBinary(const UA_Argument *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_ARGUMENT], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_Argument_decodeBinary(const UA_ByteString *src, size_t *offset, UA_Argument *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_ARGUMENT], NULL);
-}
-
-/* EnumValueType */
-static UA_INLINE size_t
-UA_EnumValueType_calcSizeBinary(const UA_EnumValueType *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_ENUMVALUETYPE]);
-}
-static UA_INLINE UA_StatusCode
-UA_EnumValueType_encodeBinary(const UA_EnumValueType *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_ENUMVALUETYPE], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_EnumValueType_decodeBinary(const UA_ByteString *src, size_t *offset, UA_EnumValueType *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_ENUMVALUETYPE], NULL);
-}
-
-/* EnumField */
-static UA_INLINE size_t
-UA_EnumField_calcSizeBinary(const UA_EnumField *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_ENUMFIELD]);
-}
-static UA_INLINE UA_StatusCode
-UA_EnumField_encodeBinary(const UA_EnumField *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_ENUMFIELD], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_EnumField_decodeBinary(const UA_ByteString *src, size_t *offset, UA_EnumField *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_ENUMFIELD], NULL);
-}
-
-/* Duration */
-static UA_INLINE size_t
-UA_Duration_calcSizeBinary(const UA_Duration *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_DURATION]);
-}
-static UA_INLINE UA_StatusCode
-UA_Duration_encodeBinary(const UA_Duration *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_DURATION], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_Duration_decodeBinary(const UA_ByteString *src, size_t *offset, UA_Duration *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_DURATION], NULL);
-}
-
-/* UtcTime */
-static UA_INLINE size_t
-UA_UtcTime_calcSizeBinary(const UA_UtcTime *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_UTCTIME]);
-}
-static UA_INLINE UA_StatusCode
-UA_UtcTime_encodeBinary(const UA_UtcTime *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_UTCTIME], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_UtcTime_decodeBinary(const UA_ByteString *src, size_t *offset, UA_UtcTime *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_UTCTIME], NULL);
-}
-
-/* LocaleId */
-static UA_INLINE size_t
-UA_LocaleId_calcSizeBinary(const UA_LocaleId *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_LOCALEID]);
-}
-static UA_INLINE UA_StatusCode
-UA_LocaleId_encodeBinary(const UA_LocaleId *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_LOCALEID], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_LocaleId_decodeBinary(const UA_ByteString *src, size_t *offset, UA_LocaleId *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_LOCALEID], NULL);
-}
-
-/* TimeZoneDataType */
-static UA_INLINE size_t
-UA_TimeZoneDataType_calcSizeBinary(const UA_TimeZoneDataType *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_TIMEZONEDATATYPE]);
-}
-static UA_INLINE UA_StatusCode
-UA_TimeZoneDataType_encodeBinary(const UA_TimeZoneDataType *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_TIMEZONEDATATYPE], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_TimeZoneDataType_decodeBinary(const UA_ByteString *src, size_t *offset, UA_TimeZoneDataType *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_TIMEZONEDATATYPE], NULL);
-}
-
-/* ApplicationType */
-static UA_INLINE size_t
-UA_ApplicationType_calcSizeBinary(const UA_ApplicationType *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_APPLICATIONTYPE]);
-}
-static UA_INLINE UA_StatusCode
-UA_ApplicationType_encodeBinary(const UA_ApplicationType *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_APPLICATIONTYPE], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_ApplicationType_decodeBinary(const UA_ByteString *src, size_t *offset, UA_ApplicationType *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_APPLICATIONTYPE], NULL);
-}
-
-/* ApplicationDescription */
-static UA_INLINE size_t
-UA_ApplicationDescription_calcSizeBinary(const UA_ApplicationDescription *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_APPLICATIONDESCRIPTION]);
-}
-static UA_INLINE UA_StatusCode
-UA_ApplicationDescription_encodeBinary(const UA_ApplicationDescription *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_APPLICATIONDESCRIPTION], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_ApplicationDescription_decodeBinary(const UA_ByteString *src, size_t *offset, UA_ApplicationDescription *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_APPLICATIONDESCRIPTION], NULL);
-}
-
-/* RequestHeader */
-static UA_INLINE size_t
-UA_RequestHeader_calcSizeBinary(const UA_RequestHeader *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_REQUESTHEADER]);
-}
-static UA_INLINE UA_StatusCode
-UA_RequestHeader_encodeBinary(const UA_RequestHeader *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_REQUESTHEADER], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_RequestHeader_decodeBinary(const UA_ByteString *src, size_t *offset, UA_RequestHeader *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_REQUESTHEADER], NULL);
-}
-
-/* ResponseHeader */
-static UA_INLINE size_t
-UA_ResponseHeader_calcSizeBinary(const UA_ResponseHeader *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_RESPONSEHEADER]);
-}
-static UA_INLINE UA_StatusCode
-UA_ResponseHeader_encodeBinary(const UA_ResponseHeader *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_RESPONSEHEADER], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_ResponseHeader_decodeBinary(const UA_ByteString *src, size_t *offset, UA_ResponseHeader *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_RESPONSEHEADER], NULL);
-}
-
-/* ServiceFault */
-static UA_INLINE size_t
-UA_ServiceFault_calcSizeBinary(const UA_ServiceFault *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_SERVICEFAULT]);
-}
-static UA_INLINE UA_StatusCode
-UA_ServiceFault_encodeBinary(const UA_ServiceFault *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_SERVICEFAULT], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_ServiceFault_decodeBinary(const UA_ByteString *src, size_t *offset, UA_ServiceFault *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_SERVICEFAULT], NULL);
-}
-
-/* FindServersRequest */
-static UA_INLINE size_t
-UA_FindServersRequest_calcSizeBinary(const UA_FindServersRequest *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_FINDSERVERSREQUEST]);
-}
-static UA_INLINE UA_StatusCode
-UA_FindServersRequest_encodeBinary(const UA_FindServersRequest *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_FINDSERVERSREQUEST], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_FindServersRequest_decodeBinary(const UA_ByteString *src, size_t *offset, UA_FindServersRequest *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_FINDSERVERSREQUEST], NULL);
-}
-
-/* FindServersResponse */
-static UA_INLINE size_t
-UA_FindServersResponse_calcSizeBinary(const UA_FindServersResponse *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_FINDSERVERSRESPONSE]);
-}
-static UA_INLINE UA_StatusCode
-UA_FindServersResponse_encodeBinary(const UA_FindServersResponse *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_FINDSERVERSRESPONSE], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_FindServersResponse_decodeBinary(const UA_ByteString *src, size_t *offset, UA_FindServersResponse *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_FINDSERVERSRESPONSE], NULL);
-}
-
-/* MessageSecurityMode */
-static UA_INLINE size_t
-UA_MessageSecurityMode_calcSizeBinary(const UA_MessageSecurityMode *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_MESSAGESECURITYMODE]);
-}
-static UA_INLINE UA_StatusCode
-UA_MessageSecurityMode_encodeBinary(const UA_MessageSecurityMode *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_MESSAGESECURITYMODE], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_MessageSecurityMode_decodeBinary(const UA_ByteString *src, size_t *offset, UA_MessageSecurityMode *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_MESSAGESECURITYMODE], NULL);
-}
-
-/* UserTokenType */
-static UA_INLINE size_t
-UA_UserTokenType_calcSizeBinary(const UA_UserTokenType *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_USERTOKENTYPE]);
-}
-static UA_INLINE UA_StatusCode
-UA_UserTokenType_encodeBinary(const UA_UserTokenType *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_USERTOKENTYPE], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_UserTokenType_decodeBinary(const UA_ByteString *src, size_t *offset, UA_UserTokenType *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_USERTOKENTYPE], NULL);
-}
-
-/* UserTokenPolicy */
-static UA_INLINE size_t
-UA_UserTokenPolicy_calcSizeBinary(const UA_UserTokenPolicy *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_USERTOKENPOLICY]);
-}
-static UA_INLINE UA_StatusCode
-UA_UserTokenPolicy_encodeBinary(const UA_UserTokenPolicy *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_USERTOKENPOLICY], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_UserTokenPolicy_decodeBinary(const UA_ByteString *src, size_t *offset, UA_UserTokenPolicy *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_USERTOKENPOLICY], NULL);
-}
-
-/* EndpointDescription */
-static UA_INLINE size_t
-UA_EndpointDescription_calcSizeBinary(const UA_EndpointDescription *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION]);
-}
-static UA_INLINE UA_StatusCode
-UA_EndpointDescription_encodeBinary(const UA_EndpointDescription *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_EndpointDescription_decodeBinary(const UA_ByteString *src, size_t *offset, UA_EndpointDescription *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION], NULL);
-}
-
-/* GetEndpointsRequest */
-static UA_INLINE size_t
-UA_GetEndpointsRequest_calcSizeBinary(const UA_GetEndpointsRequest *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_GETENDPOINTSREQUEST]);
-}
-static UA_INLINE UA_StatusCode
-UA_GetEndpointsRequest_encodeBinary(const UA_GetEndpointsRequest *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_GETENDPOINTSREQUEST], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_GetEndpointsRequest_decodeBinary(const UA_ByteString *src, size_t *offset, UA_GetEndpointsRequest *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_GETENDPOINTSREQUEST], NULL);
-}
-
-/* GetEndpointsResponse */
-static UA_INLINE size_t
-UA_GetEndpointsResponse_calcSizeBinary(const UA_GetEndpointsResponse *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_GETENDPOINTSRESPONSE]);
-}
-static UA_INLINE UA_StatusCode
-UA_GetEndpointsResponse_encodeBinary(const UA_GetEndpointsResponse *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_GETENDPOINTSRESPONSE], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_GetEndpointsResponse_decodeBinary(const UA_ByteString *src, size_t *offset, UA_GetEndpointsResponse *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_GETENDPOINTSRESPONSE], NULL);
-}
-
-/* SecurityTokenRequestType */
-static UA_INLINE size_t
-UA_SecurityTokenRequestType_calcSizeBinary(const UA_SecurityTokenRequestType *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_SECURITYTOKENREQUESTTYPE]);
-}
-static UA_INLINE UA_StatusCode
-UA_SecurityTokenRequestType_encodeBinary(const UA_SecurityTokenRequestType *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_SECURITYTOKENREQUESTTYPE], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_SecurityTokenRequestType_decodeBinary(const UA_ByteString *src, size_t *offset, UA_SecurityTokenRequestType *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_SECURITYTOKENREQUESTTYPE], NULL);
-}
-
-/* ChannelSecurityToken */
-static UA_INLINE size_t
-UA_ChannelSecurityToken_calcSizeBinary(const UA_ChannelSecurityToken *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_CHANNELSECURITYTOKEN]);
-}
-static UA_INLINE UA_StatusCode
-UA_ChannelSecurityToken_encodeBinary(const UA_ChannelSecurityToken *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_CHANNELSECURITYTOKEN], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_ChannelSecurityToken_decodeBinary(const UA_ByteString *src, size_t *offset, UA_ChannelSecurityToken *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_CHANNELSECURITYTOKEN], NULL);
-}
-
-/* OpenSecureChannelRequest */
-static UA_INLINE size_t
-UA_OpenSecureChannelRequest_calcSizeBinary(const UA_OpenSecureChannelRequest *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_OPENSECURECHANNELREQUEST]);
-}
-static UA_INLINE UA_StatusCode
-UA_OpenSecureChannelRequest_encodeBinary(const UA_OpenSecureChannelRequest *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_OPENSECURECHANNELREQUEST], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_OpenSecureChannelRequest_decodeBinary(const UA_ByteString *src, size_t *offset, UA_OpenSecureChannelRequest *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_OPENSECURECHANNELREQUEST], NULL);
-}
-
-/* OpenSecureChannelResponse */
-static UA_INLINE size_t
-UA_OpenSecureChannelResponse_calcSizeBinary(const UA_OpenSecureChannelResponse *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_OPENSECURECHANNELRESPONSE]);
-}
-static UA_INLINE UA_StatusCode
-UA_OpenSecureChannelResponse_encodeBinary(const UA_OpenSecureChannelResponse *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_OPENSECURECHANNELRESPONSE], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_OpenSecureChannelResponse_decodeBinary(const UA_ByteString *src, size_t *offset, UA_OpenSecureChannelResponse *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_OPENSECURECHANNELRESPONSE], NULL);
-}
-
-/* CloseSecureChannelRequest */
-static UA_INLINE size_t
-UA_CloseSecureChannelRequest_calcSizeBinary(const UA_CloseSecureChannelRequest *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_CLOSESECURECHANNELREQUEST]);
-}
-static UA_INLINE UA_StatusCode
-UA_CloseSecureChannelRequest_encodeBinary(const UA_CloseSecureChannelRequest *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_CLOSESECURECHANNELREQUEST], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_CloseSecureChannelRequest_decodeBinary(const UA_ByteString *src, size_t *offset, UA_CloseSecureChannelRequest *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_CLOSESECURECHANNELREQUEST], NULL);
-}
-
-/* CloseSecureChannelResponse */
-static UA_INLINE size_t
-UA_CloseSecureChannelResponse_calcSizeBinary(const UA_CloseSecureChannelResponse *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_CLOSESECURECHANNELRESPONSE]);
-}
-static UA_INLINE UA_StatusCode
-UA_CloseSecureChannelResponse_encodeBinary(const UA_CloseSecureChannelResponse *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_CLOSESECURECHANNELRESPONSE], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_CloseSecureChannelResponse_decodeBinary(const UA_ByteString *src, size_t *offset, UA_CloseSecureChannelResponse *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_CLOSESECURECHANNELRESPONSE], NULL);
-}
-
-/* SignedSoftwareCertificate */
-static UA_INLINE size_t
-UA_SignedSoftwareCertificate_calcSizeBinary(const UA_SignedSoftwareCertificate *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_SIGNEDSOFTWARECERTIFICATE]);
-}
-static UA_INLINE UA_StatusCode
-UA_SignedSoftwareCertificate_encodeBinary(const UA_SignedSoftwareCertificate *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_SIGNEDSOFTWARECERTIFICATE], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_SignedSoftwareCertificate_decodeBinary(const UA_ByteString *src, size_t *offset, UA_SignedSoftwareCertificate *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_SIGNEDSOFTWARECERTIFICATE], NULL);
-}
-
-/* SignatureData */
-static UA_INLINE size_t
-UA_SignatureData_calcSizeBinary(const UA_SignatureData *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_SIGNATUREDATA]);
-}
-static UA_INLINE UA_StatusCode
-UA_SignatureData_encodeBinary(const UA_SignatureData *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_SIGNATUREDATA], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_SignatureData_decodeBinary(const UA_ByteString *src, size_t *offset, UA_SignatureData *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_SIGNATUREDATA], NULL);
-}
-
-/* CreateSessionRequest */
-static UA_INLINE size_t
-UA_CreateSessionRequest_calcSizeBinary(const UA_CreateSessionRequest *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_CREATESESSIONREQUEST]);
-}
-static UA_INLINE UA_StatusCode
-UA_CreateSessionRequest_encodeBinary(const UA_CreateSessionRequest *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_CREATESESSIONREQUEST], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_CreateSessionRequest_decodeBinary(const UA_ByteString *src, size_t *offset, UA_CreateSessionRequest *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_CREATESESSIONREQUEST], NULL);
-}
-
-/* CreateSessionResponse */
-static UA_INLINE size_t
-UA_CreateSessionResponse_calcSizeBinary(const UA_CreateSessionResponse *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_CREATESESSIONRESPONSE]);
-}
-static UA_INLINE UA_StatusCode
-UA_CreateSessionResponse_encodeBinary(const UA_CreateSessionResponse *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_CREATESESSIONRESPONSE], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_CreateSessionResponse_decodeBinary(const UA_ByteString *src, size_t *offset, UA_CreateSessionResponse *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_CREATESESSIONRESPONSE], NULL);
-}
-
-/* UserIdentityToken */
-static UA_INLINE size_t
-UA_UserIdentityToken_calcSizeBinary(const UA_UserIdentityToken *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_USERIDENTITYTOKEN]);
-}
-static UA_INLINE UA_StatusCode
-UA_UserIdentityToken_encodeBinary(const UA_UserIdentityToken *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_USERIDENTITYTOKEN], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_UserIdentityToken_decodeBinary(const UA_ByteString *src, size_t *offset, UA_UserIdentityToken *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_USERIDENTITYTOKEN], NULL);
-}
-
-/* AnonymousIdentityToken */
-static UA_INLINE size_t
-UA_AnonymousIdentityToken_calcSizeBinary(const UA_AnonymousIdentityToken *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_ANONYMOUSIDENTITYTOKEN]);
-}
-static UA_INLINE UA_StatusCode
-UA_AnonymousIdentityToken_encodeBinary(const UA_AnonymousIdentityToken *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_ANONYMOUSIDENTITYTOKEN], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_AnonymousIdentityToken_decodeBinary(const UA_ByteString *src, size_t *offset, UA_AnonymousIdentityToken *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_ANONYMOUSIDENTITYTOKEN], NULL);
-}
-
-/* UserNameIdentityToken */
-static UA_INLINE size_t
-UA_UserNameIdentityToken_calcSizeBinary(const UA_UserNameIdentityToken *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_USERNAMEIDENTITYTOKEN]);
-}
-static UA_INLINE UA_StatusCode
-UA_UserNameIdentityToken_encodeBinary(const UA_UserNameIdentityToken *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_USERNAMEIDENTITYTOKEN], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_UserNameIdentityToken_decodeBinary(const UA_ByteString *src, size_t *offset, UA_UserNameIdentityToken *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_USERNAMEIDENTITYTOKEN], NULL);
-}
-
-/* X509IdentityToken */
-static UA_INLINE size_t
-UA_X509IdentityToken_calcSizeBinary(const UA_X509IdentityToken *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_X509IDENTITYTOKEN]);
-}
-static UA_INLINE UA_StatusCode
-UA_X509IdentityToken_encodeBinary(const UA_X509IdentityToken *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_X509IDENTITYTOKEN], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_X509IdentityToken_decodeBinary(const UA_ByteString *src, size_t *offset, UA_X509IdentityToken *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_X509IDENTITYTOKEN], NULL);
-}
-
-/* IssuedIdentityToken */
-static UA_INLINE size_t
-UA_IssuedIdentityToken_calcSizeBinary(const UA_IssuedIdentityToken *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_ISSUEDIDENTITYTOKEN]);
-}
-static UA_INLINE UA_StatusCode
-UA_IssuedIdentityToken_encodeBinary(const UA_IssuedIdentityToken *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_ISSUEDIDENTITYTOKEN], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_IssuedIdentityToken_decodeBinary(const UA_ByteString *src, size_t *offset, UA_IssuedIdentityToken *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_ISSUEDIDENTITYTOKEN], NULL);
-}
-
-/* ActivateSessionRequest */
-static UA_INLINE size_t
-UA_ActivateSessionRequest_calcSizeBinary(const UA_ActivateSessionRequest *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_ACTIVATESESSIONREQUEST]);
-}
-static UA_INLINE UA_StatusCode
-UA_ActivateSessionRequest_encodeBinary(const UA_ActivateSessionRequest *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_ACTIVATESESSIONREQUEST], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_ActivateSessionRequest_decodeBinary(const UA_ByteString *src, size_t *offset, UA_ActivateSessionRequest *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_ACTIVATESESSIONREQUEST], NULL);
-}
-
-/* ActivateSessionResponse */
-static UA_INLINE size_t
-UA_ActivateSessionResponse_calcSizeBinary(const UA_ActivateSessionResponse *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_ACTIVATESESSIONRESPONSE]);
-}
-static UA_INLINE UA_StatusCode
-UA_ActivateSessionResponse_encodeBinary(const UA_ActivateSessionResponse *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_ACTIVATESESSIONRESPONSE], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_ActivateSessionResponse_decodeBinary(const UA_ByteString *src, size_t *offset, UA_ActivateSessionResponse *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_ACTIVATESESSIONRESPONSE], NULL);
-}
-
-/* CloseSessionRequest */
-static UA_INLINE size_t
-UA_CloseSessionRequest_calcSizeBinary(const UA_CloseSessionRequest *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_CLOSESESSIONREQUEST]);
-}
-static UA_INLINE UA_StatusCode
-UA_CloseSessionRequest_encodeBinary(const UA_CloseSessionRequest *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_CLOSESESSIONREQUEST], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_CloseSessionRequest_decodeBinary(const UA_ByteString *src, size_t *offset, UA_CloseSessionRequest *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_CLOSESESSIONREQUEST], NULL);
-}
-
-/* CloseSessionResponse */
-static UA_INLINE size_t
-UA_CloseSessionResponse_calcSizeBinary(const UA_CloseSessionResponse *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_CLOSESESSIONRESPONSE]);
-}
-static UA_INLINE UA_StatusCode
-UA_CloseSessionResponse_encodeBinary(const UA_CloseSessionResponse *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_CLOSESESSIONRESPONSE], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_CloseSessionResponse_decodeBinary(const UA_ByteString *src, size_t *offset, UA_CloseSessionResponse *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_CLOSESESSIONRESPONSE], NULL);
-}
-
-/* NodeAttributesMask */
-static UA_INLINE size_t
-UA_NodeAttributesMask_calcSizeBinary(const UA_NodeAttributesMask *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_NODEATTRIBUTESMASK]);
-}
-static UA_INLINE UA_StatusCode
-UA_NodeAttributesMask_encodeBinary(const UA_NodeAttributesMask *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_NODEATTRIBUTESMASK], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_NodeAttributesMask_decodeBinary(const UA_ByteString *src, size_t *offset, UA_NodeAttributesMask *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_NODEATTRIBUTESMASK], NULL);
-}
-
-/* NodeAttributes */
-static UA_INLINE size_t
-UA_NodeAttributes_calcSizeBinary(const UA_NodeAttributes *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_NODEATTRIBUTES]);
-}
-static UA_INLINE UA_StatusCode
-UA_NodeAttributes_encodeBinary(const UA_NodeAttributes *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_NODEATTRIBUTES], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_NodeAttributes_decodeBinary(const UA_ByteString *src, size_t *offset, UA_NodeAttributes *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_NODEATTRIBUTES], NULL);
-}
-
-/* ObjectAttributes */
-static UA_INLINE size_t
-UA_ObjectAttributes_calcSizeBinary(const UA_ObjectAttributes *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES]);
-}
-static UA_INLINE UA_StatusCode
-UA_ObjectAttributes_encodeBinary(const UA_ObjectAttributes *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_ObjectAttributes_decodeBinary(const UA_ByteString *src, size_t *offset, UA_ObjectAttributes *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES], NULL);
-}
-
-/* VariableAttributes */
-static UA_INLINE size_t
-UA_VariableAttributes_calcSizeBinary(const UA_VariableAttributes *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES]);
-}
-static UA_INLINE UA_StatusCode
-UA_VariableAttributes_encodeBinary(const UA_VariableAttributes *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_VariableAttributes_decodeBinary(const UA_ByteString *src, size_t *offset, UA_VariableAttributes *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES], NULL);
-}
-
-/* MethodAttributes */
-static UA_INLINE size_t
-UA_MethodAttributes_calcSizeBinary(const UA_MethodAttributes *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_METHODATTRIBUTES]);
-}
-static UA_INLINE UA_StatusCode
-UA_MethodAttributes_encodeBinary(const UA_MethodAttributes *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_METHODATTRIBUTES], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_MethodAttributes_decodeBinary(const UA_ByteString *src, size_t *offset, UA_MethodAttributes *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_METHODATTRIBUTES], NULL);
-}
-
-/* ObjectTypeAttributes */
-static UA_INLINE size_t
-UA_ObjectTypeAttributes_calcSizeBinary(const UA_ObjectTypeAttributes *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES]);
-}
-static UA_INLINE UA_StatusCode
-UA_ObjectTypeAttributes_encodeBinary(const UA_ObjectTypeAttributes *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_ObjectTypeAttributes_decodeBinary(const UA_ByteString *src, size_t *offset, UA_ObjectTypeAttributes *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES], NULL);
-}
-
-/* VariableTypeAttributes */
-static UA_INLINE size_t
-UA_VariableTypeAttributes_calcSizeBinary(const UA_VariableTypeAttributes *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES]);
-}
-static UA_INLINE UA_StatusCode
-UA_VariableTypeAttributes_encodeBinary(const UA_VariableTypeAttributes *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_VariableTypeAttributes_decodeBinary(const UA_ByteString *src, size_t *offset, UA_VariableTypeAttributes *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES], NULL);
-}
-
-/* ReferenceTypeAttributes */
-static UA_INLINE size_t
-UA_ReferenceTypeAttributes_calcSizeBinary(const UA_ReferenceTypeAttributes *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES]);
-}
-static UA_INLINE UA_StatusCode
-UA_ReferenceTypeAttributes_encodeBinary(const UA_ReferenceTypeAttributes *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_ReferenceTypeAttributes_decodeBinary(const UA_ByteString *src, size_t *offset, UA_ReferenceTypeAttributes *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES], NULL);
-}
-
-/* DataTypeAttributes */
-static UA_INLINE size_t
-UA_DataTypeAttributes_calcSizeBinary(const UA_DataTypeAttributes *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES]);
-}
-static UA_INLINE UA_StatusCode
-UA_DataTypeAttributes_encodeBinary(const UA_DataTypeAttributes *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_DataTypeAttributes_decodeBinary(const UA_ByteString *src, size_t *offset, UA_DataTypeAttributes *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES], NULL);
-}
-
-/* ViewAttributes */
-static UA_INLINE size_t
-UA_ViewAttributes_calcSizeBinary(const UA_ViewAttributes *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_VIEWATTRIBUTES]);
-}
-static UA_INLINE UA_StatusCode
-UA_ViewAttributes_encodeBinary(const UA_ViewAttributes *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_VIEWATTRIBUTES], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_ViewAttributes_decodeBinary(const UA_ByteString *src, size_t *offset, UA_ViewAttributes *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_VIEWATTRIBUTES], NULL);
-}
-
-/* AddNodesItem */
-static UA_INLINE size_t
-UA_AddNodesItem_calcSizeBinary(const UA_AddNodesItem *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_ADDNODESITEM]);
-}
-static UA_INLINE UA_StatusCode
-UA_AddNodesItem_encodeBinary(const UA_AddNodesItem *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_ADDNODESITEM], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_AddNodesItem_decodeBinary(const UA_ByteString *src, size_t *offset, UA_AddNodesItem *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_ADDNODESITEM], NULL);
-}
-
-/* AddNodesResult */
-static UA_INLINE size_t
-UA_AddNodesResult_calcSizeBinary(const UA_AddNodesResult *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_ADDNODESRESULT]);
-}
-static UA_INLINE UA_StatusCode
-UA_AddNodesResult_encodeBinary(const UA_AddNodesResult *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_ADDNODESRESULT], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_AddNodesResult_decodeBinary(const UA_ByteString *src, size_t *offset, UA_AddNodesResult *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_ADDNODESRESULT], NULL);
-}
-
-/* AddNodesRequest */
-static UA_INLINE size_t
-UA_AddNodesRequest_calcSizeBinary(const UA_AddNodesRequest *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_ADDNODESREQUEST]);
-}
-static UA_INLINE UA_StatusCode
-UA_AddNodesRequest_encodeBinary(const UA_AddNodesRequest *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_ADDNODESREQUEST], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_AddNodesRequest_decodeBinary(const UA_ByteString *src, size_t *offset, UA_AddNodesRequest *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_ADDNODESREQUEST], NULL);
-}
-
-/* AddNodesResponse */
-static UA_INLINE size_t
-UA_AddNodesResponse_calcSizeBinary(const UA_AddNodesResponse *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_ADDNODESRESPONSE]);
-}
-static UA_INLINE UA_StatusCode
-UA_AddNodesResponse_encodeBinary(const UA_AddNodesResponse *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_ADDNODESRESPONSE], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_AddNodesResponse_decodeBinary(const UA_ByteString *src, size_t *offset, UA_AddNodesResponse *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_ADDNODESRESPONSE], NULL);
-}
-
-/* AddReferencesItem */
-static UA_INLINE size_t
-UA_AddReferencesItem_calcSizeBinary(const UA_AddReferencesItem *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_ADDREFERENCESITEM]);
-}
-static UA_INLINE UA_StatusCode
-UA_AddReferencesItem_encodeBinary(const UA_AddReferencesItem *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_ADDREFERENCESITEM], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_AddReferencesItem_decodeBinary(const UA_ByteString *src, size_t *offset, UA_AddReferencesItem *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_ADDREFERENCESITEM], NULL);
-}
-
-/* AddReferencesRequest */
-static UA_INLINE size_t
-UA_AddReferencesRequest_calcSizeBinary(const UA_AddReferencesRequest *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_ADDREFERENCESREQUEST]);
-}
-static UA_INLINE UA_StatusCode
-UA_AddReferencesRequest_encodeBinary(const UA_AddReferencesRequest *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_ADDREFERENCESREQUEST], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_AddReferencesRequest_decodeBinary(const UA_ByteString *src, size_t *offset, UA_AddReferencesRequest *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_ADDREFERENCESREQUEST], NULL);
-}
-
-/* AddReferencesResponse */
-static UA_INLINE size_t
-UA_AddReferencesResponse_calcSizeBinary(const UA_AddReferencesResponse *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_ADDREFERENCESRESPONSE]);
-}
-static UA_INLINE UA_StatusCode
-UA_AddReferencesResponse_encodeBinary(const UA_AddReferencesResponse *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_ADDREFERENCESRESPONSE], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_AddReferencesResponse_decodeBinary(const UA_ByteString *src, size_t *offset, UA_AddReferencesResponse *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_ADDREFERENCESRESPONSE], NULL);
-}
-
-/* DeleteNodesItem */
-static UA_INLINE size_t
-UA_DeleteNodesItem_calcSizeBinary(const UA_DeleteNodesItem *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_DELETENODESITEM]);
-}
-static UA_INLINE UA_StatusCode
-UA_DeleteNodesItem_encodeBinary(const UA_DeleteNodesItem *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_DELETENODESITEM], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_DeleteNodesItem_decodeBinary(const UA_ByteString *src, size_t *offset, UA_DeleteNodesItem *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_DELETENODESITEM], NULL);
-}
-
-/* DeleteNodesRequest */
-static UA_INLINE size_t
-UA_DeleteNodesRequest_calcSizeBinary(const UA_DeleteNodesRequest *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_DELETENODESREQUEST]);
-}
-static UA_INLINE UA_StatusCode
-UA_DeleteNodesRequest_encodeBinary(const UA_DeleteNodesRequest *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_DELETENODESREQUEST], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_DeleteNodesRequest_decodeBinary(const UA_ByteString *src, size_t *offset, UA_DeleteNodesRequest *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_DELETENODESREQUEST], NULL);
-}
-
-/* DeleteNodesResponse */
-static UA_INLINE size_t
-UA_DeleteNodesResponse_calcSizeBinary(const UA_DeleteNodesResponse *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_DELETENODESRESPONSE]);
-}
-static UA_INLINE UA_StatusCode
-UA_DeleteNodesResponse_encodeBinary(const UA_DeleteNodesResponse *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_DELETENODESRESPONSE], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_DeleteNodesResponse_decodeBinary(const UA_ByteString *src, size_t *offset, UA_DeleteNodesResponse *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_DELETENODESRESPONSE], NULL);
-}
-
-/* DeleteReferencesItem */
-static UA_INLINE size_t
-UA_DeleteReferencesItem_calcSizeBinary(const UA_DeleteReferencesItem *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_DELETEREFERENCESITEM]);
-}
-static UA_INLINE UA_StatusCode
-UA_DeleteReferencesItem_encodeBinary(const UA_DeleteReferencesItem *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_DELETEREFERENCESITEM], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_DeleteReferencesItem_decodeBinary(const UA_ByteString *src, size_t *offset, UA_DeleteReferencesItem *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_DELETEREFERENCESITEM], NULL);
-}
-
-/* DeleteReferencesRequest */
-static UA_INLINE size_t
-UA_DeleteReferencesRequest_calcSizeBinary(const UA_DeleteReferencesRequest *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_DELETEREFERENCESREQUEST]);
-}
-static UA_INLINE UA_StatusCode
-UA_DeleteReferencesRequest_encodeBinary(const UA_DeleteReferencesRequest *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_DELETEREFERENCESREQUEST], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_DeleteReferencesRequest_decodeBinary(const UA_ByteString *src, size_t *offset, UA_DeleteReferencesRequest *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_DELETEREFERENCESREQUEST], NULL);
-}
-
-/* DeleteReferencesResponse */
-static UA_INLINE size_t
-UA_DeleteReferencesResponse_calcSizeBinary(const UA_DeleteReferencesResponse *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_DELETEREFERENCESRESPONSE]);
-}
-static UA_INLINE UA_StatusCode
-UA_DeleteReferencesResponse_encodeBinary(const UA_DeleteReferencesResponse *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_DELETEREFERENCESRESPONSE], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_DeleteReferencesResponse_decodeBinary(const UA_ByteString *src, size_t *offset, UA_DeleteReferencesResponse *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_DELETEREFERENCESRESPONSE], NULL);
-}
-
-/* BrowseDirection */
-static UA_INLINE size_t
-UA_BrowseDirection_calcSizeBinary(const UA_BrowseDirection *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_BROWSEDIRECTION]);
-}
-static UA_INLINE UA_StatusCode
-UA_BrowseDirection_encodeBinary(const UA_BrowseDirection *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_BROWSEDIRECTION], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_BrowseDirection_decodeBinary(const UA_ByteString *src, size_t *offset, UA_BrowseDirection *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_BROWSEDIRECTION], NULL);
-}
-
-/* ViewDescription */
-static UA_INLINE size_t
-UA_ViewDescription_calcSizeBinary(const UA_ViewDescription *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_VIEWDESCRIPTION]);
-}
-static UA_INLINE UA_StatusCode
-UA_ViewDescription_encodeBinary(const UA_ViewDescription *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_VIEWDESCRIPTION], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_ViewDescription_decodeBinary(const UA_ByteString *src, size_t *offset, UA_ViewDescription *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_VIEWDESCRIPTION], NULL);
-}
-
-/* BrowseDescription */
-static UA_INLINE size_t
-UA_BrowseDescription_calcSizeBinary(const UA_BrowseDescription *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_BROWSEDESCRIPTION]);
-}
-static UA_INLINE UA_StatusCode
-UA_BrowseDescription_encodeBinary(const UA_BrowseDescription *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_BROWSEDESCRIPTION], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_BrowseDescription_decodeBinary(const UA_ByteString *src, size_t *offset, UA_BrowseDescription *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_BROWSEDESCRIPTION], NULL);
-}
-
-/* BrowseResultMask */
-static UA_INLINE size_t
-UA_BrowseResultMask_calcSizeBinary(const UA_BrowseResultMask *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_BROWSERESULTMASK]);
-}
-static UA_INLINE UA_StatusCode
-UA_BrowseResultMask_encodeBinary(const UA_BrowseResultMask *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_BROWSERESULTMASK], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_BrowseResultMask_decodeBinary(const UA_ByteString *src, size_t *offset, UA_BrowseResultMask *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_BROWSERESULTMASK], NULL);
-}
-
-/* ReferenceDescription */
-static UA_INLINE size_t
-UA_ReferenceDescription_calcSizeBinary(const UA_ReferenceDescription *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_REFERENCEDESCRIPTION]);
-}
-static UA_INLINE UA_StatusCode
-UA_ReferenceDescription_encodeBinary(const UA_ReferenceDescription *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_REFERENCEDESCRIPTION], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_ReferenceDescription_decodeBinary(const UA_ByteString *src, size_t *offset, UA_ReferenceDescription *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_REFERENCEDESCRIPTION], NULL);
-}
-
-/* BrowseResult */
-static UA_INLINE size_t
-UA_BrowseResult_calcSizeBinary(const UA_BrowseResult *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_BROWSERESULT]);
-}
-static UA_INLINE UA_StatusCode
-UA_BrowseResult_encodeBinary(const UA_BrowseResult *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_BROWSERESULT], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_BrowseResult_decodeBinary(const UA_ByteString *src, size_t *offset, UA_BrowseResult *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_BROWSERESULT], NULL);
-}
-
-/* BrowseRequest */
-static UA_INLINE size_t
-UA_BrowseRequest_calcSizeBinary(const UA_BrowseRequest *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_BROWSEREQUEST]);
-}
-static UA_INLINE UA_StatusCode
-UA_BrowseRequest_encodeBinary(const UA_BrowseRequest *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_BROWSEREQUEST], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_BrowseRequest_decodeBinary(const UA_ByteString *src, size_t *offset, UA_BrowseRequest *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_BROWSEREQUEST], NULL);
-}
-
-/* BrowseResponse */
-static UA_INLINE size_t
-UA_BrowseResponse_calcSizeBinary(const UA_BrowseResponse *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_BROWSERESPONSE]);
-}
-static UA_INLINE UA_StatusCode
-UA_BrowseResponse_encodeBinary(const UA_BrowseResponse *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_BROWSERESPONSE], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_BrowseResponse_decodeBinary(const UA_ByteString *src, size_t *offset, UA_BrowseResponse *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_BROWSERESPONSE], NULL);
-}
-
-/* BrowseNextRequest */
-static UA_INLINE size_t
-UA_BrowseNextRequest_calcSizeBinary(const UA_BrowseNextRequest *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_BROWSENEXTREQUEST]);
-}
-static UA_INLINE UA_StatusCode
-UA_BrowseNextRequest_encodeBinary(const UA_BrowseNextRequest *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_BROWSENEXTREQUEST], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_BrowseNextRequest_decodeBinary(const UA_ByteString *src, size_t *offset, UA_BrowseNextRequest *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_BROWSENEXTREQUEST], NULL);
-}
-
-/* BrowseNextResponse */
-static UA_INLINE size_t
-UA_BrowseNextResponse_calcSizeBinary(const UA_BrowseNextResponse *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_BROWSENEXTRESPONSE]);
-}
-static UA_INLINE UA_StatusCode
-UA_BrowseNextResponse_encodeBinary(const UA_BrowseNextResponse *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_BROWSENEXTRESPONSE], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_BrowseNextResponse_decodeBinary(const UA_ByteString *src, size_t *offset, UA_BrowseNextResponse *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_BROWSENEXTRESPONSE], NULL);
-}
-
-/* RelativePathElement */
-static UA_INLINE size_t
-UA_RelativePathElement_calcSizeBinary(const UA_RelativePathElement *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_RELATIVEPATHELEMENT]);
-}
-static UA_INLINE UA_StatusCode
-UA_RelativePathElement_encodeBinary(const UA_RelativePathElement *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_RELATIVEPATHELEMENT], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_RelativePathElement_decodeBinary(const UA_ByteString *src, size_t *offset, UA_RelativePathElement *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_RELATIVEPATHELEMENT], NULL);
-}
-
-/* RelativePath */
-static UA_INLINE size_t
-UA_RelativePath_calcSizeBinary(const UA_RelativePath *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_RELATIVEPATH]);
-}
-static UA_INLINE UA_StatusCode
-UA_RelativePath_encodeBinary(const UA_RelativePath *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_RELATIVEPATH], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_RelativePath_decodeBinary(const UA_ByteString *src, size_t *offset, UA_RelativePath *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_RELATIVEPATH], NULL);
-}
-
-/* BrowsePath */
-static UA_INLINE size_t
-UA_BrowsePath_calcSizeBinary(const UA_BrowsePath *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_BROWSEPATH]);
-}
-static UA_INLINE UA_StatusCode
-UA_BrowsePath_encodeBinary(const UA_BrowsePath *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_BROWSEPATH], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_BrowsePath_decodeBinary(const UA_ByteString *src, size_t *offset, UA_BrowsePath *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_BROWSEPATH], NULL);
-}
-
-/* BrowsePathTarget */
-static UA_INLINE size_t
-UA_BrowsePathTarget_calcSizeBinary(const UA_BrowsePathTarget *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_BROWSEPATHTARGET]);
-}
-static UA_INLINE UA_StatusCode
-UA_BrowsePathTarget_encodeBinary(const UA_BrowsePathTarget *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_BROWSEPATHTARGET], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_BrowsePathTarget_decodeBinary(const UA_ByteString *src, size_t *offset, UA_BrowsePathTarget *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_BROWSEPATHTARGET], NULL);
-}
-
-/* BrowsePathResult */
-static UA_INLINE size_t
-UA_BrowsePathResult_calcSizeBinary(const UA_BrowsePathResult *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_BROWSEPATHRESULT]);
-}
-static UA_INLINE UA_StatusCode
-UA_BrowsePathResult_encodeBinary(const UA_BrowsePathResult *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_BROWSEPATHRESULT], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_BrowsePathResult_decodeBinary(const UA_ByteString *src, size_t *offset, UA_BrowsePathResult *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_BROWSEPATHRESULT], NULL);
-}
-
-/* TranslateBrowsePathsToNodeIdsRequest */
-static UA_INLINE size_t
-UA_TranslateBrowsePathsToNodeIdsRequest_calcSizeBinary(const UA_TranslateBrowsePathsToNodeIdsRequest *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_TRANSLATEBROWSEPATHSTONODEIDSREQUEST]);
-}
-static UA_INLINE UA_StatusCode
-UA_TranslateBrowsePathsToNodeIdsRequest_encodeBinary(const UA_TranslateBrowsePathsToNodeIdsRequest *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_TRANSLATEBROWSEPATHSTONODEIDSREQUEST], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_TranslateBrowsePathsToNodeIdsRequest_decodeBinary(const UA_ByteString *src, size_t *offset, UA_TranslateBrowsePathsToNodeIdsRequest *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_TRANSLATEBROWSEPATHSTONODEIDSREQUEST], NULL);
-}
-
-/* TranslateBrowsePathsToNodeIdsResponse */
-static UA_INLINE size_t
-UA_TranslateBrowsePathsToNodeIdsResponse_calcSizeBinary(const UA_TranslateBrowsePathsToNodeIdsResponse *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_TRANSLATEBROWSEPATHSTONODEIDSRESPONSE]);
-}
-static UA_INLINE UA_StatusCode
-UA_TranslateBrowsePathsToNodeIdsResponse_encodeBinary(const UA_TranslateBrowsePathsToNodeIdsResponse *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_TRANSLATEBROWSEPATHSTONODEIDSRESPONSE], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_TranslateBrowsePathsToNodeIdsResponse_decodeBinary(const UA_ByteString *src, size_t *offset, UA_TranslateBrowsePathsToNodeIdsResponse *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_TRANSLATEBROWSEPATHSTONODEIDSRESPONSE], NULL);
-}
-
-/* RegisterNodesRequest */
-static UA_INLINE size_t
-UA_RegisterNodesRequest_calcSizeBinary(const UA_RegisterNodesRequest *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_REGISTERNODESREQUEST]);
-}
-static UA_INLINE UA_StatusCode
-UA_RegisterNodesRequest_encodeBinary(const UA_RegisterNodesRequest *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_REGISTERNODESREQUEST], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_RegisterNodesRequest_decodeBinary(const UA_ByteString *src, size_t *offset, UA_RegisterNodesRequest *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_REGISTERNODESREQUEST], NULL);
-}
-
-/* RegisterNodesResponse */
-static UA_INLINE size_t
-UA_RegisterNodesResponse_calcSizeBinary(const UA_RegisterNodesResponse *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_REGISTERNODESRESPONSE]);
-}
-static UA_INLINE UA_StatusCode
-UA_RegisterNodesResponse_encodeBinary(const UA_RegisterNodesResponse *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_REGISTERNODESRESPONSE], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_RegisterNodesResponse_decodeBinary(const UA_ByteString *src, size_t *offset, UA_RegisterNodesResponse *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_REGISTERNODESRESPONSE], NULL);
-}
-
-/* UnregisterNodesRequest */
-static UA_INLINE size_t
-UA_UnregisterNodesRequest_calcSizeBinary(const UA_UnregisterNodesRequest *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_UNREGISTERNODESREQUEST]);
-}
-static UA_INLINE UA_StatusCode
-UA_UnregisterNodesRequest_encodeBinary(const UA_UnregisterNodesRequest *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_UNREGISTERNODESREQUEST], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_UnregisterNodesRequest_decodeBinary(const UA_ByteString *src, size_t *offset, UA_UnregisterNodesRequest *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_UNREGISTERNODESREQUEST], NULL);
-}
-
-/* UnregisterNodesResponse */
-static UA_INLINE size_t
-UA_UnregisterNodesResponse_calcSizeBinary(const UA_UnregisterNodesResponse *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_UNREGISTERNODESRESPONSE]);
-}
-static UA_INLINE UA_StatusCode
-UA_UnregisterNodesResponse_encodeBinary(const UA_UnregisterNodesResponse *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_UNREGISTERNODESRESPONSE], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_UnregisterNodesResponse_decodeBinary(const UA_ByteString *src, size_t *offset, UA_UnregisterNodesResponse *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_UNREGISTERNODESRESPONSE], NULL);
-}
-
-/* FilterOperator */
-static UA_INLINE size_t
-UA_FilterOperator_calcSizeBinary(const UA_FilterOperator *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_FILTEROPERATOR]);
-}
-static UA_INLINE UA_StatusCode
-UA_FilterOperator_encodeBinary(const UA_FilterOperator *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_FILTEROPERATOR], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_FilterOperator_decodeBinary(const UA_ByteString *src, size_t *offset, UA_FilterOperator *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_FILTEROPERATOR], NULL);
-}
-
-/* ContentFilterElement */
-static UA_INLINE size_t
-UA_ContentFilterElement_calcSizeBinary(const UA_ContentFilterElement *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_CONTENTFILTERELEMENT]);
-}
-static UA_INLINE UA_StatusCode
-UA_ContentFilterElement_encodeBinary(const UA_ContentFilterElement *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_CONTENTFILTERELEMENT], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_ContentFilterElement_decodeBinary(const UA_ByteString *src, size_t *offset, UA_ContentFilterElement *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_CONTENTFILTERELEMENT], NULL);
-}
-
-/* ContentFilter */
-static UA_INLINE size_t
-UA_ContentFilter_calcSizeBinary(const UA_ContentFilter *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_CONTENTFILTER]);
-}
-static UA_INLINE UA_StatusCode
-UA_ContentFilter_encodeBinary(const UA_ContentFilter *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_CONTENTFILTER], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_ContentFilter_decodeBinary(const UA_ByteString *src, size_t *offset, UA_ContentFilter *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_CONTENTFILTER], NULL);
-}
-
-/* FilterOperand */
-static UA_INLINE size_t
-UA_FilterOperand_calcSizeBinary(const UA_FilterOperand *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_FILTEROPERAND]);
-}
-static UA_INLINE UA_StatusCode
-UA_FilterOperand_encodeBinary(const UA_FilterOperand *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_FILTEROPERAND], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_FilterOperand_decodeBinary(const UA_ByteString *src, size_t *offset, UA_FilterOperand *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_FILTEROPERAND], NULL);
-}
-
-/* ElementOperand */
-static UA_INLINE size_t
-UA_ElementOperand_calcSizeBinary(const UA_ElementOperand *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_ELEMENTOPERAND]);
-}
-static UA_INLINE UA_StatusCode
-UA_ElementOperand_encodeBinary(const UA_ElementOperand *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_ELEMENTOPERAND], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_ElementOperand_decodeBinary(const UA_ByteString *src, size_t *offset, UA_ElementOperand *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_ELEMENTOPERAND], NULL);
-}
-
-/* LiteralOperand */
-static UA_INLINE size_t
-UA_LiteralOperand_calcSizeBinary(const UA_LiteralOperand *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_LITERALOPERAND]);
-}
-static UA_INLINE UA_StatusCode
-UA_LiteralOperand_encodeBinary(const UA_LiteralOperand *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_LITERALOPERAND], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_LiteralOperand_decodeBinary(const UA_ByteString *src, size_t *offset, UA_LiteralOperand *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_LITERALOPERAND], NULL);
-}
-
-/* AttributeOperand */
-static UA_INLINE size_t
-UA_AttributeOperand_calcSizeBinary(const UA_AttributeOperand *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_ATTRIBUTEOPERAND]);
-}
-static UA_INLINE UA_StatusCode
-UA_AttributeOperand_encodeBinary(const UA_AttributeOperand *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_ATTRIBUTEOPERAND], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_AttributeOperand_decodeBinary(const UA_ByteString *src, size_t *offset, UA_AttributeOperand *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_ATTRIBUTEOPERAND], NULL);
-}
-
-/* SimpleAttributeOperand */
-static UA_INLINE size_t
-UA_SimpleAttributeOperand_calcSizeBinary(const UA_SimpleAttributeOperand *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_SIMPLEATTRIBUTEOPERAND]);
-}
-static UA_INLINE UA_StatusCode
-UA_SimpleAttributeOperand_encodeBinary(const UA_SimpleAttributeOperand *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_SIMPLEATTRIBUTEOPERAND], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_SimpleAttributeOperand_decodeBinary(const UA_ByteString *src, size_t *offset, UA_SimpleAttributeOperand *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_SIMPLEATTRIBUTEOPERAND], NULL);
-}
-
-/* ContentFilterElementResult */
-static UA_INLINE size_t
-UA_ContentFilterElementResult_calcSizeBinary(const UA_ContentFilterElementResult *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_CONTENTFILTERELEMENTRESULT]);
-}
-static UA_INLINE UA_StatusCode
-UA_ContentFilterElementResult_encodeBinary(const UA_ContentFilterElementResult *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_CONTENTFILTERELEMENTRESULT], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_ContentFilterElementResult_decodeBinary(const UA_ByteString *src, size_t *offset, UA_ContentFilterElementResult *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_CONTENTFILTERELEMENTRESULT], NULL);
-}
-
-/* ContentFilterResult */
-static UA_INLINE size_t
-UA_ContentFilterResult_calcSizeBinary(const UA_ContentFilterResult *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_CONTENTFILTERRESULT]);
-}
-static UA_INLINE UA_StatusCode
-UA_ContentFilterResult_encodeBinary(const UA_ContentFilterResult *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_CONTENTFILTERRESULT], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_ContentFilterResult_decodeBinary(const UA_ByteString *src, size_t *offset, UA_ContentFilterResult *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_CONTENTFILTERRESULT], NULL);
-}
-
-/* TimestampsToReturn */
-static UA_INLINE size_t
-UA_TimestampsToReturn_calcSizeBinary(const UA_TimestampsToReturn *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_TIMESTAMPSTORETURN]);
-}
-static UA_INLINE UA_StatusCode
-UA_TimestampsToReturn_encodeBinary(const UA_TimestampsToReturn *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_TIMESTAMPSTORETURN], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_TimestampsToReturn_decodeBinary(const UA_ByteString *src, size_t *offset, UA_TimestampsToReturn *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_TIMESTAMPSTORETURN], NULL);
-}
-
-/* ReadValueId */
-static UA_INLINE size_t
-UA_ReadValueId_calcSizeBinary(const UA_ReadValueId *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_READVALUEID]);
-}
-static UA_INLINE UA_StatusCode
-UA_ReadValueId_encodeBinary(const UA_ReadValueId *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_READVALUEID], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_ReadValueId_decodeBinary(const UA_ByteString *src, size_t *offset, UA_ReadValueId *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_READVALUEID], NULL);
-}
-
-/* ReadRequest */
-static UA_INLINE size_t
-UA_ReadRequest_calcSizeBinary(const UA_ReadRequest *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_READREQUEST]);
-}
-static UA_INLINE UA_StatusCode
-UA_ReadRequest_encodeBinary(const UA_ReadRequest *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_READREQUEST], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_ReadRequest_decodeBinary(const UA_ByteString *src, size_t *offset, UA_ReadRequest *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_READREQUEST], NULL);
-}
-
-/* ReadResponse */
-static UA_INLINE size_t
-UA_ReadResponse_calcSizeBinary(const UA_ReadResponse *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_READRESPONSE]);
-}
-static UA_INLINE UA_StatusCode
-UA_ReadResponse_encodeBinary(const UA_ReadResponse *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_READRESPONSE], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_ReadResponse_decodeBinary(const UA_ByteString *src, size_t *offset, UA_ReadResponse *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_READRESPONSE], NULL);
-}
-
-/* HistoryReadValueId */
-static UA_INLINE size_t
-UA_HistoryReadValueId_calcSizeBinary(const UA_HistoryReadValueId *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_HISTORYREADVALUEID]);
-}
-static UA_INLINE UA_StatusCode
-UA_HistoryReadValueId_encodeBinary(const UA_HistoryReadValueId *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_HISTORYREADVALUEID], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_HistoryReadValueId_decodeBinary(const UA_ByteString *src, size_t *offset, UA_HistoryReadValueId *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_HISTORYREADVALUEID], NULL);
-}
-
-/* HistoryReadResult */
-static UA_INLINE size_t
-UA_HistoryReadResult_calcSizeBinary(const UA_HistoryReadResult *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_HISTORYREADRESULT]);
-}
-static UA_INLINE UA_StatusCode
-UA_HistoryReadResult_encodeBinary(const UA_HistoryReadResult *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_HISTORYREADRESULT], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_HistoryReadResult_decodeBinary(const UA_ByteString *src, size_t *offset, UA_HistoryReadResult *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_HISTORYREADRESULT], NULL);
-}
-
-/* ReadRawModifiedDetails */
-static UA_INLINE size_t
-UA_ReadRawModifiedDetails_calcSizeBinary(const UA_ReadRawModifiedDetails *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_READRAWMODIFIEDDETAILS]);
-}
-static UA_INLINE UA_StatusCode
-UA_ReadRawModifiedDetails_encodeBinary(const UA_ReadRawModifiedDetails *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_READRAWMODIFIEDDETAILS], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_ReadRawModifiedDetails_decodeBinary(const UA_ByteString *src, size_t *offset, UA_ReadRawModifiedDetails *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_READRAWMODIFIEDDETAILS], NULL);
-}
-
-/* ReadAtTimeDetails */
-static UA_INLINE size_t
-UA_ReadAtTimeDetails_calcSizeBinary(const UA_ReadAtTimeDetails *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_READATTIMEDETAILS]);
-}
-static UA_INLINE UA_StatusCode
-UA_ReadAtTimeDetails_encodeBinary(const UA_ReadAtTimeDetails *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_READATTIMEDETAILS], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_ReadAtTimeDetails_decodeBinary(const UA_ByteString *src, size_t *offset, UA_ReadAtTimeDetails *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_READATTIMEDETAILS], NULL);
-}
-
-/* HistoryData */
-static UA_INLINE size_t
-UA_HistoryData_calcSizeBinary(const UA_HistoryData *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_HISTORYDATA]);
-}
-static UA_INLINE UA_StatusCode
-UA_HistoryData_encodeBinary(const UA_HistoryData *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_HISTORYDATA], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_HistoryData_decodeBinary(const UA_ByteString *src, size_t *offset, UA_HistoryData *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_HISTORYDATA], NULL);
-}
-
-/* HistoryReadRequest */
-static UA_INLINE size_t
-UA_HistoryReadRequest_calcSizeBinary(const UA_HistoryReadRequest *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_HISTORYREADREQUEST]);
-}
-static UA_INLINE UA_StatusCode
-UA_HistoryReadRequest_encodeBinary(const UA_HistoryReadRequest *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_HISTORYREADREQUEST], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_HistoryReadRequest_decodeBinary(const UA_ByteString *src, size_t *offset, UA_HistoryReadRequest *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_HISTORYREADREQUEST], NULL);
-}
-
-/* HistoryReadResponse */
-static UA_INLINE size_t
-UA_HistoryReadResponse_calcSizeBinary(const UA_HistoryReadResponse *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_HISTORYREADRESPONSE]);
-}
-static UA_INLINE UA_StatusCode
-UA_HistoryReadResponse_encodeBinary(const UA_HistoryReadResponse *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_HISTORYREADRESPONSE], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_HistoryReadResponse_decodeBinary(const UA_ByteString *src, size_t *offset, UA_HistoryReadResponse *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_HISTORYREADRESPONSE], NULL);
-}
-
-/* WriteValue */
-static UA_INLINE size_t
-UA_WriteValue_calcSizeBinary(const UA_WriteValue *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_WRITEVALUE]);
-}
-static UA_INLINE UA_StatusCode
-UA_WriteValue_encodeBinary(const UA_WriteValue *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_WRITEVALUE], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_WriteValue_decodeBinary(const UA_ByteString *src, size_t *offset, UA_WriteValue *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_WRITEVALUE], NULL);
-}
-
-/* WriteRequest */
-static UA_INLINE size_t
-UA_WriteRequest_calcSizeBinary(const UA_WriteRequest *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_WRITEREQUEST]);
-}
-static UA_INLINE UA_StatusCode
-UA_WriteRequest_encodeBinary(const UA_WriteRequest *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_WRITEREQUEST], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_WriteRequest_decodeBinary(const UA_ByteString *src, size_t *offset, UA_WriteRequest *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_WRITEREQUEST], NULL);
-}
-
-/* WriteResponse */
-static UA_INLINE size_t
-UA_WriteResponse_calcSizeBinary(const UA_WriteResponse *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_WRITERESPONSE]);
-}
-static UA_INLINE UA_StatusCode
-UA_WriteResponse_encodeBinary(const UA_WriteResponse *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_WRITERESPONSE], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_WriteResponse_decodeBinary(const UA_ByteString *src, size_t *offset, UA_WriteResponse *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_WRITERESPONSE], NULL);
-}
-
-/* HistoryUpdateType */
-static UA_INLINE size_t
-UA_HistoryUpdateType_calcSizeBinary(const UA_HistoryUpdateType *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_HISTORYUPDATETYPE]);
-}
-static UA_INLINE UA_StatusCode
-UA_HistoryUpdateType_encodeBinary(const UA_HistoryUpdateType *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_HISTORYUPDATETYPE], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_HistoryUpdateType_decodeBinary(const UA_ByteString *src, size_t *offset, UA_HistoryUpdateType *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_HISTORYUPDATETYPE], NULL);
-}
-
-/* PerformUpdateType */
-static UA_INLINE size_t
-UA_PerformUpdateType_calcSizeBinary(const UA_PerformUpdateType *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_PERFORMUPDATETYPE]);
-}
-static UA_INLINE UA_StatusCode
-UA_PerformUpdateType_encodeBinary(const UA_PerformUpdateType *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_PERFORMUPDATETYPE], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_PerformUpdateType_decodeBinary(const UA_ByteString *src, size_t *offset, UA_PerformUpdateType *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_PERFORMUPDATETYPE], NULL);
-}
-
-/* UpdateDataDetails */
-static UA_INLINE size_t
-UA_UpdateDataDetails_calcSizeBinary(const UA_UpdateDataDetails *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_UPDATEDATADETAILS]);
-}
-static UA_INLINE UA_StatusCode
-UA_UpdateDataDetails_encodeBinary(const UA_UpdateDataDetails *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_UPDATEDATADETAILS], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_UpdateDataDetails_decodeBinary(const UA_ByteString *src, size_t *offset, UA_UpdateDataDetails *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_UPDATEDATADETAILS], NULL);
-}
-
-/* DeleteRawModifiedDetails */
-static UA_INLINE size_t
-UA_DeleteRawModifiedDetails_calcSizeBinary(const UA_DeleteRawModifiedDetails *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_DELETERAWMODIFIEDDETAILS]);
-}
-static UA_INLINE UA_StatusCode
-UA_DeleteRawModifiedDetails_encodeBinary(const UA_DeleteRawModifiedDetails *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_DELETERAWMODIFIEDDETAILS], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_DeleteRawModifiedDetails_decodeBinary(const UA_ByteString *src, size_t *offset, UA_DeleteRawModifiedDetails *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_DELETERAWMODIFIEDDETAILS], NULL);
-}
-
-/* HistoryUpdateResult */
-static UA_INLINE size_t
-UA_HistoryUpdateResult_calcSizeBinary(const UA_HistoryUpdateResult *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_HISTORYUPDATERESULT]);
-}
-static UA_INLINE UA_StatusCode
-UA_HistoryUpdateResult_encodeBinary(const UA_HistoryUpdateResult *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_HISTORYUPDATERESULT], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_HistoryUpdateResult_decodeBinary(const UA_ByteString *src, size_t *offset, UA_HistoryUpdateResult *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_HISTORYUPDATERESULT], NULL);
-}
-
-/* HistoryUpdateRequest */
-static UA_INLINE size_t
-UA_HistoryUpdateRequest_calcSizeBinary(const UA_HistoryUpdateRequest *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_HISTORYUPDATEREQUEST]);
-}
-static UA_INLINE UA_StatusCode
-UA_HistoryUpdateRequest_encodeBinary(const UA_HistoryUpdateRequest *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_HISTORYUPDATEREQUEST], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_HistoryUpdateRequest_decodeBinary(const UA_ByteString *src, size_t *offset, UA_HistoryUpdateRequest *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_HISTORYUPDATEREQUEST], NULL);
-}
-
-/* HistoryUpdateResponse */
-static UA_INLINE size_t
-UA_HistoryUpdateResponse_calcSizeBinary(const UA_HistoryUpdateResponse *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_HISTORYUPDATERESPONSE]);
-}
-static UA_INLINE UA_StatusCode
-UA_HistoryUpdateResponse_encodeBinary(const UA_HistoryUpdateResponse *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_HISTORYUPDATERESPONSE], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_HistoryUpdateResponse_decodeBinary(const UA_ByteString *src, size_t *offset, UA_HistoryUpdateResponse *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_HISTORYUPDATERESPONSE], NULL);
-}
-
-/* CallMethodRequest */
-static UA_INLINE size_t
-UA_CallMethodRequest_calcSizeBinary(const UA_CallMethodRequest *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_CALLMETHODREQUEST]);
-}
-static UA_INLINE UA_StatusCode
-UA_CallMethodRequest_encodeBinary(const UA_CallMethodRequest *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_CALLMETHODREQUEST], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_CallMethodRequest_decodeBinary(const UA_ByteString *src, size_t *offset, UA_CallMethodRequest *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_CALLMETHODREQUEST], NULL);
-}
-
-/* CallMethodResult */
-static UA_INLINE size_t
-UA_CallMethodResult_calcSizeBinary(const UA_CallMethodResult *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_CALLMETHODRESULT]);
-}
-static UA_INLINE UA_StatusCode
-UA_CallMethodResult_encodeBinary(const UA_CallMethodResult *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_CALLMETHODRESULT], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_CallMethodResult_decodeBinary(const UA_ByteString *src, size_t *offset, UA_CallMethodResult *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_CALLMETHODRESULT], NULL);
-}
-
-/* CallRequest */
-static UA_INLINE size_t
-UA_CallRequest_calcSizeBinary(const UA_CallRequest *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_CALLREQUEST]);
-}
-static UA_INLINE UA_StatusCode
-UA_CallRequest_encodeBinary(const UA_CallRequest *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_CALLREQUEST], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_CallRequest_decodeBinary(const UA_ByteString *src, size_t *offset, UA_CallRequest *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_CALLREQUEST], NULL);
-}
-
-/* CallResponse */
-static UA_INLINE size_t
-UA_CallResponse_calcSizeBinary(const UA_CallResponse *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_CALLRESPONSE]);
-}
-static UA_INLINE UA_StatusCode
-UA_CallResponse_encodeBinary(const UA_CallResponse *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_CALLRESPONSE], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_CallResponse_decodeBinary(const UA_ByteString *src, size_t *offset, UA_CallResponse *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_CALLRESPONSE], NULL);
-}
-
-/* MonitoringMode */
-static UA_INLINE size_t
-UA_MonitoringMode_calcSizeBinary(const UA_MonitoringMode *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_MONITORINGMODE]);
-}
-static UA_INLINE UA_StatusCode
-UA_MonitoringMode_encodeBinary(const UA_MonitoringMode *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_MONITORINGMODE], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_MonitoringMode_decodeBinary(const UA_ByteString *src, size_t *offset, UA_MonitoringMode *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_MONITORINGMODE], NULL);
-}
-
-/* DataChangeTrigger */
-static UA_INLINE size_t
-UA_DataChangeTrigger_calcSizeBinary(const UA_DataChangeTrigger *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_DATACHANGETRIGGER]);
-}
-static UA_INLINE UA_StatusCode
-UA_DataChangeTrigger_encodeBinary(const UA_DataChangeTrigger *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_DATACHANGETRIGGER], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_DataChangeTrigger_decodeBinary(const UA_ByteString *src, size_t *offset, UA_DataChangeTrigger *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_DATACHANGETRIGGER], NULL);
-}
-
-/* DeadbandType */
-static UA_INLINE size_t
-UA_DeadbandType_calcSizeBinary(const UA_DeadbandType *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_DEADBANDTYPE]);
-}
-static UA_INLINE UA_StatusCode
-UA_DeadbandType_encodeBinary(const UA_DeadbandType *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_DEADBANDTYPE], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_DeadbandType_decodeBinary(const UA_ByteString *src, size_t *offset, UA_DeadbandType *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_DEADBANDTYPE], NULL);
-}
-
-/* DataChangeFilter */
-static UA_INLINE size_t
-UA_DataChangeFilter_calcSizeBinary(const UA_DataChangeFilter *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_DATACHANGEFILTER]);
-}
-static UA_INLINE UA_StatusCode
-UA_DataChangeFilter_encodeBinary(const UA_DataChangeFilter *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_DATACHANGEFILTER], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_DataChangeFilter_decodeBinary(const UA_ByteString *src, size_t *offset, UA_DataChangeFilter *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_DATACHANGEFILTER], NULL);
-}
-
-/* EventFilter */
-static UA_INLINE size_t
-UA_EventFilter_calcSizeBinary(const UA_EventFilter *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_EVENTFILTER]);
-}
-static UA_INLINE UA_StatusCode
-UA_EventFilter_encodeBinary(const UA_EventFilter *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_EVENTFILTER], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_EventFilter_decodeBinary(const UA_ByteString *src, size_t *offset, UA_EventFilter *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_EVENTFILTER], NULL);
-}
-
-/* AggregateConfiguration */
-static UA_INLINE size_t
-UA_AggregateConfiguration_calcSizeBinary(const UA_AggregateConfiguration *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_AGGREGATECONFIGURATION]);
-}
-static UA_INLINE UA_StatusCode
-UA_AggregateConfiguration_encodeBinary(const UA_AggregateConfiguration *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_AGGREGATECONFIGURATION], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_AggregateConfiguration_decodeBinary(const UA_ByteString *src, size_t *offset, UA_AggregateConfiguration *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_AGGREGATECONFIGURATION], NULL);
-}
-
-/* AggregateFilter */
-static UA_INLINE size_t
-UA_AggregateFilter_calcSizeBinary(const UA_AggregateFilter *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_AGGREGATEFILTER]);
-}
-static UA_INLINE UA_StatusCode
-UA_AggregateFilter_encodeBinary(const UA_AggregateFilter *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_AGGREGATEFILTER], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_AggregateFilter_decodeBinary(const UA_ByteString *src, size_t *offset, UA_AggregateFilter *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_AGGREGATEFILTER], NULL);
-}
-
-/* EventFilterResult */
-static UA_INLINE size_t
-UA_EventFilterResult_calcSizeBinary(const UA_EventFilterResult *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_EVENTFILTERRESULT]);
-}
-static UA_INLINE UA_StatusCode
-UA_EventFilterResult_encodeBinary(const UA_EventFilterResult *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_EVENTFILTERRESULT], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_EventFilterResult_decodeBinary(const UA_ByteString *src, size_t *offset, UA_EventFilterResult *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_EVENTFILTERRESULT], NULL);
-}
-
-/* MonitoringParameters */
-static UA_INLINE size_t
-UA_MonitoringParameters_calcSizeBinary(const UA_MonitoringParameters *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_MONITORINGPARAMETERS]);
-}
-static UA_INLINE UA_StatusCode
-UA_MonitoringParameters_encodeBinary(const UA_MonitoringParameters *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_MONITORINGPARAMETERS], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_MonitoringParameters_decodeBinary(const UA_ByteString *src, size_t *offset, UA_MonitoringParameters *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_MONITORINGPARAMETERS], NULL);
-}
-
-/* MonitoredItemCreateRequest */
-static UA_INLINE size_t
-UA_MonitoredItemCreateRequest_calcSizeBinary(const UA_MonitoredItemCreateRequest *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_MONITOREDITEMCREATEREQUEST]);
-}
-static UA_INLINE UA_StatusCode
-UA_MonitoredItemCreateRequest_encodeBinary(const UA_MonitoredItemCreateRequest *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_MONITOREDITEMCREATEREQUEST], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_MonitoredItemCreateRequest_decodeBinary(const UA_ByteString *src, size_t *offset, UA_MonitoredItemCreateRequest *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_MONITOREDITEMCREATEREQUEST], NULL);
-}
-
-/* MonitoredItemCreateResult */
-static UA_INLINE size_t
-UA_MonitoredItemCreateResult_calcSizeBinary(const UA_MonitoredItemCreateResult *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_MONITOREDITEMCREATERESULT]);
-}
-static UA_INLINE UA_StatusCode
-UA_MonitoredItemCreateResult_encodeBinary(const UA_MonitoredItemCreateResult *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_MONITOREDITEMCREATERESULT], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_MonitoredItemCreateResult_decodeBinary(const UA_ByteString *src, size_t *offset, UA_MonitoredItemCreateResult *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_MONITOREDITEMCREATERESULT], NULL);
-}
-
-/* CreateMonitoredItemsRequest */
-static UA_INLINE size_t
-UA_CreateMonitoredItemsRequest_calcSizeBinary(const UA_CreateMonitoredItemsRequest *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_CREATEMONITOREDITEMSREQUEST]);
-}
-static UA_INLINE UA_StatusCode
-UA_CreateMonitoredItemsRequest_encodeBinary(const UA_CreateMonitoredItemsRequest *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_CREATEMONITOREDITEMSREQUEST], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_CreateMonitoredItemsRequest_decodeBinary(const UA_ByteString *src, size_t *offset, UA_CreateMonitoredItemsRequest *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_CREATEMONITOREDITEMSREQUEST], NULL);
-}
-
-/* CreateMonitoredItemsResponse */
-static UA_INLINE size_t
-UA_CreateMonitoredItemsResponse_calcSizeBinary(const UA_CreateMonitoredItemsResponse *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_CREATEMONITOREDITEMSRESPONSE]);
-}
-static UA_INLINE UA_StatusCode
-UA_CreateMonitoredItemsResponse_encodeBinary(const UA_CreateMonitoredItemsResponse *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_CREATEMONITOREDITEMSRESPONSE], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_CreateMonitoredItemsResponse_decodeBinary(const UA_ByteString *src, size_t *offset, UA_CreateMonitoredItemsResponse *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_CREATEMONITOREDITEMSRESPONSE], NULL);
-}
-
-/* MonitoredItemModifyRequest */
-static UA_INLINE size_t
-UA_MonitoredItemModifyRequest_calcSizeBinary(const UA_MonitoredItemModifyRequest *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_MONITOREDITEMMODIFYREQUEST]);
-}
-static UA_INLINE UA_StatusCode
-UA_MonitoredItemModifyRequest_encodeBinary(const UA_MonitoredItemModifyRequest *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_MONITOREDITEMMODIFYREQUEST], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_MonitoredItemModifyRequest_decodeBinary(const UA_ByteString *src, size_t *offset, UA_MonitoredItemModifyRequest *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_MONITOREDITEMMODIFYREQUEST], NULL);
-}
-
-/* MonitoredItemModifyResult */
-static UA_INLINE size_t
-UA_MonitoredItemModifyResult_calcSizeBinary(const UA_MonitoredItemModifyResult *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_MONITOREDITEMMODIFYRESULT]);
-}
-static UA_INLINE UA_StatusCode
-UA_MonitoredItemModifyResult_encodeBinary(const UA_MonitoredItemModifyResult *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_MONITOREDITEMMODIFYRESULT], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_MonitoredItemModifyResult_decodeBinary(const UA_ByteString *src, size_t *offset, UA_MonitoredItemModifyResult *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_MONITOREDITEMMODIFYRESULT], NULL);
-}
-
-/* ModifyMonitoredItemsRequest */
-static UA_INLINE size_t
-UA_ModifyMonitoredItemsRequest_calcSizeBinary(const UA_ModifyMonitoredItemsRequest *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_MODIFYMONITOREDITEMSREQUEST]);
-}
-static UA_INLINE UA_StatusCode
-UA_ModifyMonitoredItemsRequest_encodeBinary(const UA_ModifyMonitoredItemsRequest *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_MODIFYMONITOREDITEMSREQUEST], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_ModifyMonitoredItemsRequest_decodeBinary(const UA_ByteString *src, size_t *offset, UA_ModifyMonitoredItemsRequest *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_MODIFYMONITOREDITEMSREQUEST], NULL);
-}
-
-/* ModifyMonitoredItemsResponse */
-static UA_INLINE size_t
-UA_ModifyMonitoredItemsResponse_calcSizeBinary(const UA_ModifyMonitoredItemsResponse *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_MODIFYMONITOREDITEMSRESPONSE]);
-}
-static UA_INLINE UA_StatusCode
-UA_ModifyMonitoredItemsResponse_encodeBinary(const UA_ModifyMonitoredItemsResponse *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_MODIFYMONITOREDITEMSRESPONSE], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_ModifyMonitoredItemsResponse_decodeBinary(const UA_ByteString *src, size_t *offset, UA_ModifyMonitoredItemsResponse *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_MODIFYMONITOREDITEMSRESPONSE], NULL);
-}
-
-/* SetMonitoringModeRequest */
-static UA_INLINE size_t
-UA_SetMonitoringModeRequest_calcSizeBinary(const UA_SetMonitoringModeRequest *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_SETMONITORINGMODEREQUEST]);
-}
-static UA_INLINE UA_StatusCode
-UA_SetMonitoringModeRequest_encodeBinary(const UA_SetMonitoringModeRequest *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_SETMONITORINGMODEREQUEST], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_SetMonitoringModeRequest_decodeBinary(const UA_ByteString *src, size_t *offset, UA_SetMonitoringModeRequest *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_SETMONITORINGMODEREQUEST], NULL);
-}
-
-/* SetMonitoringModeResponse */
-static UA_INLINE size_t
-UA_SetMonitoringModeResponse_calcSizeBinary(const UA_SetMonitoringModeResponse *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_SETMONITORINGMODERESPONSE]);
-}
-static UA_INLINE UA_StatusCode
-UA_SetMonitoringModeResponse_encodeBinary(const UA_SetMonitoringModeResponse *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_SETMONITORINGMODERESPONSE], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_SetMonitoringModeResponse_decodeBinary(const UA_ByteString *src, size_t *offset, UA_SetMonitoringModeResponse *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_SETMONITORINGMODERESPONSE], NULL);
-}
-
-/* SetTriggeringRequest */
-static UA_INLINE size_t
-UA_SetTriggeringRequest_calcSizeBinary(const UA_SetTriggeringRequest *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_SETTRIGGERINGREQUEST]);
-}
-static UA_INLINE UA_StatusCode
-UA_SetTriggeringRequest_encodeBinary(const UA_SetTriggeringRequest *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_SETTRIGGERINGREQUEST], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_SetTriggeringRequest_decodeBinary(const UA_ByteString *src, size_t *offset, UA_SetTriggeringRequest *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_SETTRIGGERINGREQUEST], NULL);
-}
-
-/* SetTriggeringResponse */
-static UA_INLINE size_t
-UA_SetTriggeringResponse_calcSizeBinary(const UA_SetTriggeringResponse *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_SETTRIGGERINGRESPONSE]);
-}
-static UA_INLINE UA_StatusCode
-UA_SetTriggeringResponse_encodeBinary(const UA_SetTriggeringResponse *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_SETTRIGGERINGRESPONSE], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_SetTriggeringResponse_decodeBinary(const UA_ByteString *src, size_t *offset, UA_SetTriggeringResponse *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_SETTRIGGERINGRESPONSE], NULL);
-}
-
-/* DeleteMonitoredItemsRequest */
-static UA_INLINE size_t
-UA_DeleteMonitoredItemsRequest_calcSizeBinary(const UA_DeleteMonitoredItemsRequest *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_DELETEMONITOREDITEMSREQUEST]);
-}
-static UA_INLINE UA_StatusCode
-UA_DeleteMonitoredItemsRequest_encodeBinary(const UA_DeleteMonitoredItemsRequest *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_DELETEMONITOREDITEMSREQUEST], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_DeleteMonitoredItemsRequest_decodeBinary(const UA_ByteString *src, size_t *offset, UA_DeleteMonitoredItemsRequest *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_DELETEMONITOREDITEMSREQUEST], NULL);
-}
-
-/* DeleteMonitoredItemsResponse */
-static UA_INLINE size_t
-UA_DeleteMonitoredItemsResponse_calcSizeBinary(const UA_DeleteMonitoredItemsResponse *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_DELETEMONITOREDITEMSRESPONSE]);
-}
-static UA_INLINE UA_StatusCode
-UA_DeleteMonitoredItemsResponse_encodeBinary(const UA_DeleteMonitoredItemsResponse *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_DELETEMONITOREDITEMSRESPONSE], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_DeleteMonitoredItemsResponse_decodeBinary(const UA_ByteString *src, size_t *offset, UA_DeleteMonitoredItemsResponse *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_DELETEMONITOREDITEMSRESPONSE], NULL);
-}
-
-/* CreateSubscriptionRequest */
-static UA_INLINE size_t
-UA_CreateSubscriptionRequest_calcSizeBinary(const UA_CreateSubscriptionRequest *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_CREATESUBSCRIPTIONREQUEST]);
-}
-static UA_INLINE UA_StatusCode
-UA_CreateSubscriptionRequest_encodeBinary(const UA_CreateSubscriptionRequest *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_CREATESUBSCRIPTIONREQUEST], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_CreateSubscriptionRequest_decodeBinary(const UA_ByteString *src, size_t *offset, UA_CreateSubscriptionRequest *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_CREATESUBSCRIPTIONREQUEST], NULL);
-}
-
-/* CreateSubscriptionResponse */
-static UA_INLINE size_t
-UA_CreateSubscriptionResponse_calcSizeBinary(const UA_CreateSubscriptionResponse *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_CREATESUBSCRIPTIONRESPONSE]);
-}
-static UA_INLINE UA_StatusCode
-UA_CreateSubscriptionResponse_encodeBinary(const UA_CreateSubscriptionResponse *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_CREATESUBSCRIPTIONRESPONSE], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_CreateSubscriptionResponse_decodeBinary(const UA_ByteString *src, size_t *offset, UA_CreateSubscriptionResponse *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_CREATESUBSCRIPTIONRESPONSE], NULL);
-}
-
-/* ModifySubscriptionRequest */
-static UA_INLINE size_t
-UA_ModifySubscriptionRequest_calcSizeBinary(const UA_ModifySubscriptionRequest *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_MODIFYSUBSCRIPTIONREQUEST]);
-}
-static UA_INLINE UA_StatusCode
-UA_ModifySubscriptionRequest_encodeBinary(const UA_ModifySubscriptionRequest *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_MODIFYSUBSCRIPTIONREQUEST], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_ModifySubscriptionRequest_decodeBinary(const UA_ByteString *src, size_t *offset, UA_ModifySubscriptionRequest *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_MODIFYSUBSCRIPTIONREQUEST], NULL);
-}
-
-/* ModifySubscriptionResponse */
-static UA_INLINE size_t
-UA_ModifySubscriptionResponse_calcSizeBinary(const UA_ModifySubscriptionResponse *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_MODIFYSUBSCRIPTIONRESPONSE]);
-}
-static UA_INLINE UA_StatusCode
-UA_ModifySubscriptionResponse_encodeBinary(const UA_ModifySubscriptionResponse *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_MODIFYSUBSCRIPTIONRESPONSE], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_ModifySubscriptionResponse_decodeBinary(const UA_ByteString *src, size_t *offset, UA_ModifySubscriptionResponse *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_MODIFYSUBSCRIPTIONRESPONSE], NULL);
-}
-
-/* SetPublishingModeRequest */
-static UA_INLINE size_t
-UA_SetPublishingModeRequest_calcSizeBinary(const UA_SetPublishingModeRequest *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_SETPUBLISHINGMODEREQUEST]);
-}
-static UA_INLINE UA_StatusCode
-UA_SetPublishingModeRequest_encodeBinary(const UA_SetPublishingModeRequest *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_SETPUBLISHINGMODEREQUEST], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_SetPublishingModeRequest_decodeBinary(const UA_ByteString *src, size_t *offset, UA_SetPublishingModeRequest *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_SETPUBLISHINGMODEREQUEST], NULL);
-}
-
-/* SetPublishingModeResponse */
-static UA_INLINE size_t
-UA_SetPublishingModeResponse_calcSizeBinary(const UA_SetPublishingModeResponse *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_SETPUBLISHINGMODERESPONSE]);
-}
-static UA_INLINE UA_StatusCode
-UA_SetPublishingModeResponse_encodeBinary(const UA_SetPublishingModeResponse *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_SETPUBLISHINGMODERESPONSE], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_SetPublishingModeResponse_decodeBinary(const UA_ByteString *src, size_t *offset, UA_SetPublishingModeResponse *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_SETPUBLISHINGMODERESPONSE], NULL);
-}
-
-/* NotificationMessage */
-static UA_INLINE size_t
-UA_NotificationMessage_calcSizeBinary(const UA_NotificationMessage *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_NOTIFICATIONMESSAGE]);
-}
-static UA_INLINE UA_StatusCode
-UA_NotificationMessage_encodeBinary(const UA_NotificationMessage *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_NOTIFICATIONMESSAGE], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_NotificationMessage_decodeBinary(const UA_ByteString *src, size_t *offset, UA_NotificationMessage *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_NOTIFICATIONMESSAGE], NULL);
-}
-
-/* MonitoredItemNotification */
-static UA_INLINE size_t
-UA_MonitoredItemNotification_calcSizeBinary(const UA_MonitoredItemNotification *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_MONITOREDITEMNOTIFICATION]);
-}
-static UA_INLINE UA_StatusCode
-UA_MonitoredItemNotification_encodeBinary(const UA_MonitoredItemNotification *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_MONITOREDITEMNOTIFICATION], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_MonitoredItemNotification_decodeBinary(const UA_ByteString *src, size_t *offset, UA_MonitoredItemNotification *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_MONITOREDITEMNOTIFICATION], NULL);
-}
-
-/* EventFieldList */
-static UA_INLINE size_t
-UA_EventFieldList_calcSizeBinary(const UA_EventFieldList *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_EVENTFIELDLIST]);
-}
-static UA_INLINE UA_StatusCode
-UA_EventFieldList_encodeBinary(const UA_EventFieldList *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_EVENTFIELDLIST], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_EventFieldList_decodeBinary(const UA_ByteString *src, size_t *offset, UA_EventFieldList *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_EVENTFIELDLIST], NULL);
-}
-
-/* HistoryEventFieldList */
-static UA_INLINE size_t
-UA_HistoryEventFieldList_calcSizeBinary(const UA_HistoryEventFieldList *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_HISTORYEVENTFIELDLIST]);
-}
-static UA_INLINE UA_StatusCode
-UA_HistoryEventFieldList_encodeBinary(const UA_HistoryEventFieldList *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_HISTORYEVENTFIELDLIST], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_HistoryEventFieldList_decodeBinary(const UA_ByteString *src, size_t *offset, UA_HistoryEventFieldList *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_HISTORYEVENTFIELDLIST], NULL);
-}
-
-/* StatusChangeNotification */
-static UA_INLINE size_t
-UA_StatusChangeNotification_calcSizeBinary(const UA_StatusChangeNotification *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_STATUSCHANGENOTIFICATION]);
-}
-static UA_INLINE UA_StatusCode
-UA_StatusChangeNotification_encodeBinary(const UA_StatusChangeNotification *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_STATUSCHANGENOTIFICATION], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_StatusChangeNotification_decodeBinary(const UA_ByteString *src, size_t *offset, UA_StatusChangeNotification *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_STATUSCHANGENOTIFICATION], NULL);
-}
-
-/* SubscriptionAcknowledgement */
-static UA_INLINE size_t
-UA_SubscriptionAcknowledgement_calcSizeBinary(const UA_SubscriptionAcknowledgement *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_SUBSCRIPTIONACKNOWLEDGEMENT]);
-}
-static UA_INLINE UA_StatusCode
-UA_SubscriptionAcknowledgement_encodeBinary(const UA_SubscriptionAcknowledgement *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_SUBSCRIPTIONACKNOWLEDGEMENT], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_SubscriptionAcknowledgement_decodeBinary(const UA_ByteString *src, size_t *offset, UA_SubscriptionAcknowledgement *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_SUBSCRIPTIONACKNOWLEDGEMENT], NULL);
-}
-
-/* PublishRequest */
-static UA_INLINE size_t
-UA_PublishRequest_calcSizeBinary(const UA_PublishRequest *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_PUBLISHREQUEST]);
-}
-static UA_INLINE UA_StatusCode
-UA_PublishRequest_encodeBinary(const UA_PublishRequest *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_PUBLISHREQUEST], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_PublishRequest_decodeBinary(const UA_ByteString *src, size_t *offset, UA_PublishRequest *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_PUBLISHREQUEST], NULL);
-}
-
-/* PublishResponse */
-static UA_INLINE size_t
-UA_PublishResponse_calcSizeBinary(const UA_PublishResponse *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_PUBLISHRESPONSE]);
-}
-static UA_INLINE UA_StatusCode
-UA_PublishResponse_encodeBinary(const UA_PublishResponse *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_PUBLISHRESPONSE], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_PublishResponse_decodeBinary(const UA_ByteString *src, size_t *offset, UA_PublishResponse *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_PUBLISHRESPONSE], NULL);
-}
-
-/* RepublishRequest */
-static UA_INLINE size_t
-UA_RepublishRequest_calcSizeBinary(const UA_RepublishRequest *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_REPUBLISHREQUEST]);
-}
-static UA_INLINE UA_StatusCode
-UA_RepublishRequest_encodeBinary(const UA_RepublishRequest *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_REPUBLISHREQUEST], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_RepublishRequest_decodeBinary(const UA_ByteString *src, size_t *offset, UA_RepublishRequest *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_REPUBLISHREQUEST], NULL);
-}
-
-/* RepublishResponse */
-static UA_INLINE size_t
-UA_RepublishResponse_calcSizeBinary(const UA_RepublishResponse *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_REPUBLISHRESPONSE]);
-}
-static UA_INLINE UA_StatusCode
-UA_RepublishResponse_encodeBinary(const UA_RepublishResponse *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_REPUBLISHRESPONSE], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_RepublishResponse_decodeBinary(const UA_ByteString *src, size_t *offset, UA_RepublishResponse *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_REPUBLISHRESPONSE], NULL);
-}
-
-/* DeleteSubscriptionsRequest */
-static UA_INLINE size_t
-UA_DeleteSubscriptionsRequest_calcSizeBinary(const UA_DeleteSubscriptionsRequest *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_DELETESUBSCRIPTIONSREQUEST]);
-}
-static UA_INLINE UA_StatusCode
-UA_DeleteSubscriptionsRequest_encodeBinary(const UA_DeleteSubscriptionsRequest *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_DELETESUBSCRIPTIONSREQUEST], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_DeleteSubscriptionsRequest_decodeBinary(const UA_ByteString *src, size_t *offset, UA_DeleteSubscriptionsRequest *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_DELETESUBSCRIPTIONSREQUEST], NULL);
-}
-
-/* DeleteSubscriptionsResponse */
-static UA_INLINE size_t
-UA_DeleteSubscriptionsResponse_calcSizeBinary(const UA_DeleteSubscriptionsResponse *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_DELETESUBSCRIPTIONSRESPONSE]);
-}
-static UA_INLINE UA_StatusCode
-UA_DeleteSubscriptionsResponse_encodeBinary(const UA_DeleteSubscriptionsResponse *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_DELETESUBSCRIPTIONSRESPONSE], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_DeleteSubscriptionsResponse_decodeBinary(const UA_ByteString *src, size_t *offset, UA_DeleteSubscriptionsResponse *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_DELETESUBSCRIPTIONSRESPONSE], NULL);
-}
-
-/* BuildInfo */
-static UA_INLINE size_t
-UA_BuildInfo_calcSizeBinary(const UA_BuildInfo *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_BUILDINFO]);
-}
-static UA_INLINE UA_StatusCode
-UA_BuildInfo_encodeBinary(const UA_BuildInfo *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_BUILDINFO], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_BuildInfo_decodeBinary(const UA_ByteString *src, size_t *offset, UA_BuildInfo *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_BUILDINFO], NULL);
-}
-
-/* RedundancySupport */
-static UA_INLINE size_t
-UA_RedundancySupport_calcSizeBinary(const UA_RedundancySupport *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_REDUNDANCYSUPPORT]);
-}
-static UA_INLINE UA_StatusCode
-UA_RedundancySupport_encodeBinary(const UA_RedundancySupport *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_REDUNDANCYSUPPORT], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_RedundancySupport_decodeBinary(const UA_ByteString *src, size_t *offset, UA_RedundancySupport *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_REDUNDANCYSUPPORT], NULL);
-}
-
-/* ServerState */
-static UA_INLINE size_t
-UA_ServerState_calcSizeBinary(const UA_ServerState *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_SERVERSTATE]);
-}
-static UA_INLINE UA_StatusCode
-UA_ServerState_encodeBinary(const UA_ServerState *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_SERVERSTATE], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_ServerState_decodeBinary(const UA_ByteString *src, size_t *offset, UA_ServerState *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_SERVERSTATE], NULL);
-}
-
-/* ServerDiagnosticsSummaryDataType */
-static UA_INLINE size_t
-UA_ServerDiagnosticsSummaryDataType_calcSizeBinary(const UA_ServerDiagnosticsSummaryDataType *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_SERVERDIAGNOSTICSSUMMARYDATATYPE]);
-}
-static UA_INLINE UA_StatusCode
-UA_ServerDiagnosticsSummaryDataType_encodeBinary(const UA_ServerDiagnosticsSummaryDataType *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_SERVERDIAGNOSTICSSUMMARYDATATYPE], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_ServerDiagnosticsSummaryDataType_decodeBinary(const UA_ByteString *src, size_t *offset, UA_ServerDiagnosticsSummaryDataType *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_SERVERDIAGNOSTICSSUMMARYDATATYPE], NULL);
-}
-
-/* ServerStatusDataType */
-static UA_INLINE size_t
-UA_ServerStatusDataType_calcSizeBinary(const UA_ServerStatusDataType *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_SERVERSTATUSDATATYPE]);
-}
-static UA_INLINE UA_StatusCode
-UA_ServerStatusDataType_encodeBinary(const UA_ServerStatusDataType *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_SERVERSTATUSDATATYPE], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_ServerStatusDataType_decodeBinary(const UA_ByteString *src, size_t *offset, UA_ServerStatusDataType *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_SERVERSTATUSDATATYPE], NULL);
-}
-
-/* Range */
-static UA_INLINE size_t
-UA_Range_calcSizeBinary(const UA_Range *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_RANGE]);
-}
-static UA_INLINE UA_StatusCode
-UA_Range_encodeBinary(const UA_Range *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_RANGE], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_Range_decodeBinary(const UA_ByteString *src, size_t *offset, UA_Range *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_RANGE], NULL);
-}
-
-/* EUInformation */
-static UA_INLINE size_t
-UA_EUInformation_calcSizeBinary(const UA_EUInformation *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_EUINFORMATION]);
-}
-static UA_INLINE UA_StatusCode
-UA_EUInformation_encodeBinary(const UA_EUInformation *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_EUINFORMATION], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_EUInformation_decodeBinary(const UA_ByteString *src, size_t *offset, UA_EUInformation *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_EUINFORMATION], NULL);
-}
-
-/* AxisScaleEnumeration */
-static UA_INLINE size_t
-UA_AxisScaleEnumeration_calcSizeBinary(const UA_AxisScaleEnumeration *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_AXISSCALEENUMERATION]);
-}
-static UA_INLINE UA_StatusCode
-UA_AxisScaleEnumeration_encodeBinary(const UA_AxisScaleEnumeration *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_AXISSCALEENUMERATION], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_AxisScaleEnumeration_decodeBinary(const UA_ByteString *src, size_t *offset, UA_AxisScaleEnumeration *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_AXISSCALEENUMERATION], NULL);
-}
-
-/* ComplexNumberType */
-static UA_INLINE size_t
-UA_ComplexNumberType_calcSizeBinary(const UA_ComplexNumberType *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_COMPLEXNUMBERTYPE]);
-}
-static UA_INLINE UA_StatusCode
-UA_ComplexNumberType_encodeBinary(const UA_ComplexNumberType *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_COMPLEXNUMBERTYPE], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_ComplexNumberType_decodeBinary(const UA_ByteString *src, size_t *offset, UA_ComplexNumberType *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_COMPLEXNUMBERTYPE], NULL);
-}
-
-/* DoubleComplexNumberType */
-static UA_INLINE size_t
-UA_DoubleComplexNumberType_calcSizeBinary(const UA_DoubleComplexNumberType *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_DOUBLECOMPLEXNUMBERTYPE]);
-}
-static UA_INLINE UA_StatusCode
-UA_DoubleComplexNumberType_encodeBinary(const UA_DoubleComplexNumberType *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_DOUBLECOMPLEXNUMBERTYPE], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_DoubleComplexNumberType_decodeBinary(const UA_ByteString *src, size_t *offset, UA_DoubleComplexNumberType *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_DOUBLECOMPLEXNUMBERTYPE], NULL);
-}
-
-/* AxisInformation */
-static UA_INLINE size_t
-UA_AxisInformation_calcSizeBinary(const UA_AxisInformation *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_AXISINFORMATION]);
-}
-static UA_INLINE UA_StatusCode
-UA_AxisInformation_encodeBinary(const UA_AxisInformation *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_AXISINFORMATION], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_AxisInformation_decodeBinary(const UA_ByteString *src, size_t *offset, UA_AxisInformation *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_AXISINFORMATION], NULL);
-}
-
-/* XVType */
-static UA_INLINE size_t
-UA_XVType_calcSizeBinary(const UA_XVType *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_XVTYPE]);
-}
-static UA_INLINE UA_StatusCode
-UA_XVType_encodeBinary(const UA_XVType *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_XVTYPE], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_XVType_decodeBinary(const UA_ByteString *src, size_t *offset, UA_XVType *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_XVTYPE], NULL);
-}
-
-/* EnumDefinition */
-static UA_INLINE size_t
-UA_EnumDefinition_calcSizeBinary(const UA_EnumDefinition *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_ENUMDEFINITION]);
-}
-static UA_INLINE UA_StatusCode
-UA_EnumDefinition_encodeBinary(const UA_EnumDefinition *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_ENUMDEFINITION], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_EnumDefinition_decodeBinary(const UA_ByteString *src, size_t *offset, UA_EnumDefinition *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_ENUMDEFINITION], NULL);
-}
-
-/* ReadEventDetails */
-static UA_INLINE size_t
-UA_ReadEventDetails_calcSizeBinary(const UA_ReadEventDetails *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_READEVENTDETAILS]);
-}
-static UA_INLINE UA_StatusCode
-UA_ReadEventDetails_encodeBinary(const UA_ReadEventDetails *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_READEVENTDETAILS], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_ReadEventDetails_decodeBinary(const UA_ByteString *src, size_t *offset, UA_ReadEventDetails *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_READEVENTDETAILS], NULL);
-}
-
-/* ReadProcessedDetails */
-static UA_INLINE size_t
-UA_ReadProcessedDetails_calcSizeBinary(const UA_ReadProcessedDetails *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_READPROCESSEDDETAILS]);
-}
-static UA_INLINE UA_StatusCode
-UA_ReadProcessedDetails_encodeBinary(const UA_ReadProcessedDetails *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_READPROCESSEDDETAILS], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_ReadProcessedDetails_decodeBinary(const UA_ByteString *src, size_t *offset, UA_ReadProcessedDetails *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_READPROCESSEDDETAILS], NULL);
-}
-
-/* ModificationInfo */
-static UA_INLINE size_t
-UA_ModificationInfo_calcSizeBinary(const UA_ModificationInfo *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_MODIFICATIONINFO]);
-}
-static UA_INLINE UA_StatusCode
-UA_ModificationInfo_encodeBinary(const UA_ModificationInfo *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_MODIFICATIONINFO], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_ModificationInfo_decodeBinary(const UA_ByteString *src, size_t *offset, UA_ModificationInfo *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_MODIFICATIONINFO], NULL);
-}
-
-/* HistoryModifiedData */
-static UA_INLINE size_t
-UA_HistoryModifiedData_calcSizeBinary(const UA_HistoryModifiedData *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_HISTORYMODIFIEDDATA]);
-}
-static UA_INLINE UA_StatusCode
-UA_HistoryModifiedData_encodeBinary(const UA_HistoryModifiedData *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_HISTORYMODIFIEDDATA], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_HistoryModifiedData_decodeBinary(const UA_ByteString *src, size_t *offset, UA_HistoryModifiedData *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_HISTORYMODIFIEDDATA], NULL);
-}
-
-/* HistoryEvent */
-static UA_INLINE size_t
-UA_HistoryEvent_calcSizeBinary(const UA_HistoryEvent *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_HISTORYEVENT]);
-}
-static UA_INLINE UA_StatusCode
-UA_HistoryEvent_encodeBinary(const UA_HistoryEvent *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_HISTORYEVENT], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_HistoryEvent_decodeBinary(const UA_ByteString *src, size_t *offset, UA_HistoryEvent *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_HISTORYEVENT], NULL);
-}
-
-/* DataChangeNotification */
-static UA_INLINE size_t
-UA_DataChangeNotification_calcSizeBinary(const UA_DataChangeNotification *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_DATACHANGENOTIFICATION]);
-}
-static UA_INLINE UA_StatusCode
-UA_DataChangeNotification_encodeBinary(const UA_DataChangeNotification *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_DATACHANGENOTIFICATION], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_DataChangeNotification_decodeBinary(const UA_ByteString *src, size_t *offset, UA_DataChangeNotification *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_DATACHANGENOTIFICATION], NULL);
-}
-
-/* EventNotificationList */
-static UA_INLINE size_t
-UA_EventNotificationList_calcSizeBinary(const UA_EventNotificationList *src) {
- return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_EVENTNOTIFICATIONLIST]);
-}
-static UA_INLINE UA_StatusCode
-UA_EventNotificationList_encodeBinary(const UA_EventNotificationList *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_EVENTNOTIFICATIONLIST], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_EventNotificationList_decodeBinary(const UA_ByteString *src, size_t *offset, UA_EventNotificationList *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_EVENTNOTIFICATIONLIST], NULL);
-}
-
-
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/build/src_generated/open62541/transport_generated.h" ***********************************/
-
-/* Generated from Opc.Ua.Types.bsd, Custom.Opc.Ua.Transport.bsd with script /home/pdie/sonstiges/qtopcua/repos/open62541/tools/generate_datatypes.py
- * on host mintaka by user pdie at 2021-06-21 11:34:37 */
+#endif
-#ifdef UA_ENABLE_AMALGAMATION
-#else
-#endif
_UA_BEGIN_DECLS
@@ -3962,6 +1245,7 @@ typedef enum {
UA_MESSAGETYPE_OPN = 0x4E504F,
UA_MESSAGETYPE_CLO = 0x4F4C43,
UA_MESSAGETYPE_ERR = 0x525245,
+ UA_MESSAGETYPE_INVALID = 0x0,
__UA_MESSAGETYPE_FORCE32BIT = 0x7fffffff
} UA_MessageType;
UA_STATIC_ASSERT(sizeof(UA_MessageType) == sizeof(UA_Int32), enum_must_be_32bit);
@@ -4036,7 +1320,7 @@ typedef struct {
/**
* AsymmetricAlgorithmSecurityHeader
* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- * Security Header */
+ * Asymmetric Security Header */
typedef struct {
UA_ByteString securityPolicyUri;
UA_ByteString senderCertificate;
@@ -4060,10 +1344,11 @@ typedef struct {
_UA_END_DECLS
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/build/src_generated/open62541/transport_generated_handling.h" ***********************************/
+/**** amalgamated original file "/build/src_generated/open62541/transport_generated_handling.h" ****/
-/* Generated from Opc.Ua.Types.bsd, Custom.Opc.Ua.Transport.bsd with script /home/pdie/sonstiges/qtopcua/repos/open62541/tools/generate_datatypes.py
- * on host mintaka by user pdie at 2021-06-21 11:34:37 */
+/**********************************
+ * Autogenerated -- do not modify *
+ **********************************/
@@ -4092,7 +1377,7 @@ UA_MessageType_copy(const UA_MessageType *src, UA_MessageType *dst) {
return UA_copy(src, dst, &UA_TRANSPORT[UA_TRANSPORT_MESSAGETYPE]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_MessageType_deleteMembers(UA_MessageType *p) {
UA_clear(p, &UA_TRANSPORT[UA_TRANSPORT_MESSAGETYPE]);
}
@@ -4123,7 +1408,7 @@ UA_ChunkType_copy(const UA_ChunkType *src, UA_ChunkType *dst) {
return UA_copy(src, dst, &UA_TRANSPORT[UA_TRANSPORT_CHUNKTYPE]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_ChunkType_deleteMembers(UA_ChunkType *p) {
UA_clear(p, &UA_TRANSPORT[UA_TRANSPORT_CHUNKTYPE]);
}
@@ -4154,7 +1439,7 @@ UA_TcpMessageHeader_copy(const UA_TcpMessageHeader *src, UA_TcpMessageHeader *ds
return UA_copy(src, dst, &UA_TRANSPORT[UA_TRANSPORT_TCPMESSAGEHEADER]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_TcpMessageHeader_deleteMembers(UA_TcpMessageHeader *p) {
UA_clear(p, &UA_TRANSPORT[UA_TRANSPORT_TCPMESSAGEHEADER]);
}
@@ -4185,7 +1470,7 @@ UA_TcpHelloMessage_copy(const UA_TcpHelloMessage *src, UA_TcpHelloMessage *dst)
return UA_copy(src, dst, &UA_TRANSPORT[UA_TRANSPORT_TCPHELLOMESSAGE]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_TcpHelloMessage_deleteMembers(UA_TcpHelloMessage *p) {
UA_clear(p, &UA_TRANSPORT[UA_TRANSPORT_TCPHELLOMESSAGE]);
}
@@ -4216,7 +1501,7 @@ UA_TcpAcknowledgeMessage_copy(const UA_TcpAcknowledgeMessage *src, UA_TcpAcknowl
return UA_copy(src, dst, &UA_TRANSPORT[UA_TRANSPORT_TCPACKNOWLEDGEMESSAGE]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_TcpAcknowledgeMessage_deleteMembers(UA_TcpAcknowledgeMessage *p) {
UA_clear(p, &UA_TRANSPORT[UA_TRANSPORT_TCPACKNOWLEDGEMESSAGE]);
}
@@ -4247,7 +1532,7 @@ UA_TcpErrorMessage_copy(const UA_TcpErrorMessage *src, UA_TcpErrorMessage *dst)
return UA_copy(src, dst, &UA_TRANSPORT[UA_TRANSPORT_TCPERRORMESSAGE]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_TcpErrorMessage_deleteMembers(UA_TcpErrorMessage *p) {
UA_clear(p, &UA_TRANSPORT[UA_TRANSPORT_TCPERRORMESSAGE]);
}
@@ -4278,7 +1563,7 @@ UA_AsymmetricAlgorithmSecurityHeader_copy(const UA_AsymmetricAlgorithmSecurityHe
return UA_copy(src, dst, &UA_TRANSPORT[UA_TRANSPORT_ASYMMETRICALGORITHMSECURITYHEADER]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(UA_AsymmetricAlgorithmSecurityHeader *p) {
UA_clear(p, &UA_TRANSPORT[UA_TRANSPORT_ASYMMETRICALGORITHMSECURITYHEADER]);
}
@@ -4309,7 +1594,7 @@ UA_SequenceHeader_copy(const UA_SequenceHeader *src, UA_SequenceHeader *dst) {
return UA_copy(src, dst, &UA_TRANSPORT[UA_TRANSPORT_SEQUENCEHEADER]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_SequenceHeader_deleteMembers(UA_SequenceHeader *p) {
UA_clear(p, &UA_TRANSPORT[UA_TRANSPORT_SEQUENCEHEADER]);
}
@@ -4331,132 +1616,7 @@ UA_SequenceHeader_delete(UA_SequenceHeader *p) {
_UA_END_DECLS
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/build/src_generated/open62541/transport_generated_encoding_binary.h" ***********************************/
-
-/* Generated from Opc.Ua.Types.bsd, Custom.Opc.Ua.Transport.bsd with script /home/pdie/sonstiges/qtopcua/repos/open62541/tools/generate_datatypes.py
- * on host mintaka by user pdie at 2021-06-21 11:34:37 */
-
-
-#ifdef UA_ENABLE_AMALGAMATION
-#else
-#endif
-
-
-
-/* MessageType */
-static UA_INLINE size_t
-UA_MessageType_calcSizeBinary(const UA_MessageType *src) {
- return UA_calcSizeBinary(src, &UA_TRANSPORT[UA_TRANSPORT_MESSAGETYPE]);
-}
-static UA_INLINE UA_StatusCode
-UA_MessageType_encodeBinary(const UA_MessageType *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TRANSPORT[UA_TRANSPORT_MESSAGETYPE], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_MessageType_decodeBinary(const UA_ByteString *src, size_t *offset, UA_MessageType *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TRANSPORT[UA_TRANSPORT_MESSAGETYPE], NULL);
-}
-
-/* ChunkType */
-static UA_INLINE size_t
-UA_ChunkType_calcSizeBinary(const UA_ChunkType *src) {
- return UA_calcSizeBinary(src, &UA_TRANSPORT[UA_TRANSPORT_CHUNKTYPE]);
-}
-static UA_INLINE UA_StatusCode
-UA_ChunkType_encodeBinary(const UA_ChunkType *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TRANSPORT[UA_TRANSPORT_CHUNKTYPE], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_ChunkType_decodeBinary(const UA_ByteString *src, size_t *offset, UA_ChunkType *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TRANSPORT[UA_TRANSPORT_CHUNKTYPE], NULL);
-}
-
-/* TcpMessageHeader */
-static UA_INLINE size_t
-UA_TcpMessageHeader_calcSizeBinary(const UA_TcpMessageHeader *src) {
- return UA_calcSizeBinary(src, &UA_TRANSPORT[UA_TRANSPORT_TCPMESSAGEHEADER]);
-}
-static UA_INLINE UA_StatusCode
-UA_TcpMessageHeader_encodeBinary(const UA_TcpMessageHeader *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TRANSPORT[UA_TRANSPORT_TCPMESSAGEHEADER], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_TcpMessageHeader_decodeBinary(const UA_ByteString *src, size_t *offset, UA_TcpMessageHeader *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TRANSPORT[UA_TRANSPORT_TCPMESSAGEHEADER], NULL);
-}
-
-/* TcpHelloMessage */
-static UA_INLINE size_t
-UA_TcpHelloMessage_calcSizeBinary(const UA_TcpHelloMessage *src) {
- return UA_calcSizeBinary(src, &UA_TRANSPORT[UA_TRANSPORT_TCPHELLOMESSAGE]);
-}
-static UA_INLINE UA_StatusCode
-UA_TcpHelloMessage_encodeBinary(const UA_TcpHelloMessage *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TRANSPORT[UA_TRANSPORT_TCPHELLOMESSAGE], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_TcpHelloMessage_decodeBinary(const UA_ByteString *src, size_t *offset, UA_TcpHelloMessage *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TRANSPORT[UA_TRANSPORT_TCPHELLOMESSAGE], NULL);
-}
-
-/* TcpAcknowledgeMessage */
-static UA_INLINE size_t
-UA_TcpAcknowledgeMessage_calcSizeBinary(const UA_TcpAcknowledgeMessage *src) {
- return UA_calcSizeBinary(src, &UA_TRANSPORT[UA_TRANSPORT_TCPACKNOWLEDGEMESSAGE]);
-}
-static UA_INLINE UA_StatusCode
-UA_TcpAcknowledgeMessage_encodeBinary(const UA_TcpAcknowledgeMessage *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TRANSPORT[UA_TRANSPORT_TCPACKNOWLEDGEMESSAGE], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_TcpAcknowledgeMessage_decodeBinary(const UA_ByteString *src, size_t *offset, UA_TcpAcknowledgeMessage *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TRANSPORT[UA_TRANSPORT_TCPACKNOWLEDGEMESSAGE], NULL);
-}
-
-/* TcpErrorMessage */
-static UA_INLINE size_t
-UA_TcpErrorMessage_calcSizeBinary(const UA_TcpErrorMessage *src) {
- return UA_calcSizeBinary(src, &UA_TRANSPORT[UA_TRANSPORT_TCPERRORMESSAGE]);
-}
-static UA_INLINE UA_StatusCode
-UA_TcpErrorMessage_encodeBinary(const UA_TcpErrorMessage *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TRANSPORT[UA_TRANSPORT_TCPERRORMESSAGE], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_TcpErrorMessage_decodeBinary(const UA_ByteString *src, size_t *offset, UA_TcpErrorMessage *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TRANSPORT[UA_TRANSPORT_TCPERRORMESSAGE], NULL);
-}
-
-/* AsymmetricAlgorithmSecurityHeader */
-static UA_INLINE size_t
-UA_AsymmetricAlgorithmSecurityHeader_calcSizeBinary(const UA_AsymmetricAlgorithmSecurityHeader *src) {
- return UA_calcSizeBinary(src, &UA_TRANSPORT[UA_TRANSPORT_ASYMMETRICALGORITHMSECURITYHEADER]);
-}
-static UA_INLINE UA_StatusCode
-UA_AsymmetricAlgorithmSecurityHeader_encodeBinary(const UA_AsymmetricAlgorithmSecurityHeader *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TRANSPORT[UA_TRANSPORT_ASYMMETRICALGORITHMSECURITYHEADER], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_AsymmetricAlgorithmSecurityHeader_decodeBinary(const UA_ByteString *src, size_t *offset, UA_AsymmetricAlgorithmSecurityHeader *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TRANSPORT[UA_TRANSPORT_ASYMMETRICALGORITHMSECURITYHEADER], NULL);
-}
-
-/* SequenceHeader */
-static UA_INLINE size_t
-UA_SequenceHeader_calcSizeBinary(const UA_SequenceHeader *src) {
- return UA_calcSizeBinary(src, &UA_TRANSPORT[UA_TRANSPORT_SEQUENCEHEADER]);
-}
-static UA_INLINE UA_StatusCode
-UA_SequenceHeader_encodeBinary(const UA_SequenceHeader *src, UA_Byte **bufPos, const UA_Byte *bufEnd) {
- return UA_encodeBinary(src, &UA_TRANSPORT[UA_TRANSPORT_SEQUENCEHEADER], bufPos, &bufEnd, NULL, NULL);
-}
-static UA_INLINE UA_StatusCode
-UA_SequenceHeader_decodeBinary(const UA_ByteString *src, size_t *offset, UA_SequenceHeader *dst) {
- return UA_decodeBinary(src, offset, dst, &UA_TRANSPORT[UA_TRANSPORT_SEQUENCEHEADER], NULL);
-}
-
-
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/src/ua_connection_internal.h" ***********************************/
+/**** amalgamated original file "/src/ua_connection_internal.h" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -4488,7 +1648,7 @@ void UA_Connection_attachSecureChannel(UA_Connection *connection,
_UA_END_DECLS
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/src/ua_securechannel.h" ***********************************/
+/**** amalgamated original file "/src/ua_securechannel.h" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -4505,8 +1665,34 @@ _UA_END_DECLS
_UA_BEGIN_DECLS
-#define UA_SECURE_CONVERSATION_MESSAGE_HEADER_LENGTH 12
-#define UA_SECURE_MESSAGE_HEADER_LENGTH 24
+/* The message header of the OPC UA binary protocol is structured as follows:
+ *
+ * - MessageType (3 Byte)
+ * - IsFinal (1 Byte)
+ * - MessageSize (4 Byte)
+ * *** UA_SECURECHANNEL_MESSAGEHEADER_LENGTH ***
+ * - SecureChannelId (4 Byte)
+ * *** UA_SECURECHANNEL_CHANNELHEADER_LENGTH ***
+ * - SecurityHeader (4 Byte TokenId for symmetric, otherwise dynamic length)
+ * - SequenceHeader (8 Byte)
+ * - SequenceNumber
+ * - RequestId
+ */
+
+#define UA_SECURECHANNEL_MESSAGEHEADER_LENGTH 8
+#define UA_SECURECHANNEL_CHANNELHEADER_LENGTH 12
+#define UA_SECURECHANNEL_SYMMETRIC_SECURITYHEADER_LENGTH 4
+#define UA_SECURECHANNEL_SEQUENCEHEADER_LENGTH 8
+#define UA_SECURECHANNEL_SYMMETRIC_HEADER_UNENCRYPTEDLENGTH \
+ (UA_SECURECHANNEL_CHANNELHEADER_LENGTH + \
+ UA_SECURECHANNEL_SYMMETRIC_SECURITYHEADER_LENGTH)
+#define UA_SECURECHANNEL_SYMMETRIC_HEADER_TOTALLENGTH \
+ (UA_SECURECHANNEL_CHANNELHEADER_LENGTH + \
+ UA_SECURECHANNEL_SYMMETRIC_SECURITYHEADER_LENGTH + \
+ UA_SECURECHANNEL_SEQUENCEHEADER_LENGTH)
+
+/* Minimum length of a valid message (ERR message with an empty reason) */
+#define UA_SECURECHANNEL_MESSAGE_MIN_LENGTH 16
/* Thread-local variables to force failure modes during testing */
#ifdef UA_ENABLE_UNIT_TEST_FAILURE_HOOKS
@@ -4523,6 +1709,7 @@ extern UA_StatusCode processSym_seqNumberFailure;
typedef struct UA_SessionHeader {
SLIST_ENTRY(UA_SessionHeader) next;
UA_NodeId authenticationToken;
+ UA_Boolean serverSession; /* Disambiguate client and server session */
UA_SecureChannel *channel; /* The pointer back to the SecureChannel in the session. */
} UA_SessionHeader;
@@ -4532,9 +1719,9 @@ typedef struct UA_Chunk {
UA_ByteString bytes;
UA_MessageType messageType;
UA_ChunkType chunkType;
+ UA_UInt32 requestId;
UA_Boolean copied; /* Do the bytes point to a buffer from the network or was
* memory allocated for the chunk separately */
- UA_Boolean decrypted; /* The chunk has been decrypted */
} UA_Chunk;
typedef SIMPLEQ_HEAD(UA_ChunkQueue, UA_Chunk) UA_ChunkQueue;
@@ -4603,9 +1790,17 @@ struct UA_SecureChannel {
* buffers is reentrant with the correct processing order. (This has lead to
* problems in the client in the past.) */
UA_ChunkQueue completeChunks; /* Received full chunks that have not been
- * processed so far */
+ * decrypted so far */
+ UA_ChunkQueue decryptedChunks; /* Received chunks that were decrypted but
+ * not processed */
+ size_t decryptedChunksCount;
+ size_t decryptedChunksLength;
UA_ByteString incompleteChunk; /* A half-received chunk (TCP is a
* streaming protocol) is stored here */
+
+ UA_CertificateVerification *certificateVerification;
+ UA_StatusCode (*processOPNHeader)(void *application, UA_SecureChannel *channel,
+ const UA_AsymmetricAlgorithmSecurityHeader *asymHeader);
};
void UA_SecureChannel_init(UA_SecureChannel *channel,
@@ -4698,7 +1893,7 @@ UA_MessageContext_abort(UA_MessageContext *mc);
* Receive Message
* --------------- */
-typedef void
+typedef UA_StatusCode
(UA_ProcessMessageCallback)(void *application, UA_SecureChannel *channel,
UA_MessageType messageType, UA_UInt32 requestId,
UA_ByteString *message);
@@ -4759,32 +1954,24 @@ void
setBufPos(UA_MessageContext *mc);
UA_StatusCode
-checkSymHeader(UA_SecureChannel *channel, UA_UInt32 tokenId);
-
-UA_StatusCode
-processSequenceNumberAsym(UA_SecureChannel *channel, UA_UInt32 sequenceNumber);
+checkSymHeader(UA_SecureChannel *channel, const UA_UInt32 tokenId);
UA_StatusCode
checkAsymHeader(UA_SecureChannel *channel,
const UA_AsymmetricAlgorithmSecurityHeader *asymHeader);
void
-padChunkAsym(UA_SecureChannel *channel, const UA_ByteString *buf,
- size_t securityHeaderLength, UA_Byte **buf_pos);
+padChunk(UA_SecureChannel *channel, const UA_SecurityPolicyCryptoModule *cm,
+ const UA_Byte *start, UA_Byte **pos);
UA_StatusCode
signAndEncryptAsym(UA_SecureChannel *channel, size_t preSignLength,
UA_ByteString *buf, size_t securityHeaderLength,
size_t totalLength);
-void
-padChunkSym(UA_MessageContext *messageContext, size_t bodyLength);
-
-UA_StatusCode
-signChunkSym(UA_MessageContext *const messageContext, size_t preSigLength);
-
UA_StatusCode
-encryptChunkSym(UA_MessageContext *const messageContext, size_t totalLength);
+signAndEncryptSym(UA_MessageContext *messageContext,
+ size_t preSigLength, size_t totalLength);
/**
* Log Helper
@@ -4855,180 +2042,82 @@ encryptChunkSym(UA_MessageContext *const messageContext, size_t totalLength);
_UA_END_DECLS
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/src/ua_workqueue.h" ***********************************/
+/**** amalgamated original file "/src/ua_timer.h" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
- * Copyright 2014-2018 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
- * Copyright 2014-2016 (c) Sten Grüner
- * Copyright 2015 (c) Chris Iatrou
- * Copyright 2015 (c) Nick Goossens
- * Copyright 2015 (c) Jörg Schüler-Maroldt
- * Copyright 2015-2016 (c) Oleksiy Vasylyev
- * Copyright 2016-2017 (c) Florian Palm
+ * Copyright 2017, 2018, 2021 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
* Copyright 2017 (c) Stefan Profanter, fortiss GmbH
- * Copyright 2016 (c) Lorenz Haas
- * Copyright 2017 (c) Jonas Green
*/
-#if UA_MULTITHREADING >= 200
-#include <pthread.h>
-#endif
-
_UA_BEGIN_DECLS
+/* The timer is protected by its own mutex. The mutex is released before calling
+ * into the callbacks. So the timer can be modified from the callbacks it is
+ * executing. Also, the timer mutex can never lead to locking. Because the timer
+ * mutex will be left without acquiring another mutex.
+ *
+ * Obviously, the timer must not be deleted from within one of its
+ * callbacks. */
+
/* Callback where the application is either a client or a server */
typedef void (*UA_ApplicationCallback)(void *application, void *data);
-/* Delayed callbacks are executed when all previously enqueue work is finished.
- * This is used to free memory that might used by a parallel worker or where the
- * current threat has remaining pointers to until the current operation
- * finishes. */
-typedef struct UA_DelayedCallback {
- SIMPLEQ_ENTRY(UA_DelayedCallback) next;
+typedef struct UA_TimerEntry {
+ struct aa_entry treeEntry;
+ UA_TimerPolicy timerPolicy; /* Timer policy to handle cycle misses */
+ UA_DateTime nextTime; /* The next time when the callback
+ * is to be executed */
+ UA_UInt64 interval; /* Interval in 100ns resolution. If
+ the interval is zero, the
+ callback is not repeated and
+ removed after execution. */
UA_ApplicationCallback callback;
void *application;
void *data;
-} UA_DelayedCallback;
-
-struct UA_WorkQueue;
-typedef struct UA_WorkQueue UA_WorkQueue;
-#if UA_MULTITHREADING >= 200
+ struct aa_entry idTreeEntry;
+ UA_UInt64 id; /* Id of the entry */
+} UA_TimerEntry;
-/* Workers take out callbacks from the work queue and execute them.
- *
- * Future Plans: Use work-stealing to load-balance between cores.
- * Le, Nhat Minh, et al. "Correct and efficient work-stealing for weak memory
- * models." ACM SIGPLAN Notices. Vol. 48. No. 8. ACM, 2013. */
typedef struct {
- pthread_t thread;
- volatile UA_Boolean running;
- UA_WorkQueue *queue;
- UA_UInt32 counter;
- UA_UInt32 checkpointCounter; /* Counter when the last checkpoint was made
- * for the delayed callbacks */
-
- /* separate cache lines */
- char padding[64 - sizeof(void*) - sizeof(pthread_t) -
- sizeof(UA_UInt32) - sizeof(UA_Boolean)];
-} UA_Worker;
-
-#endif
-
-struct UA_WorkQueue {
- /* Worker threads and work queue. Without multithreading, work is executed
- immediately. */
-#if UA_MULTITHREADING >= 200
- UA_Worker *workers;
- size_t workersSize;
-
- /* Work queue */
- SIMPLEQ_HEAD(, UA_DelayedCallback) dispatchQueue; /* Dispatch queue for the worker threads */
- UA_LOCK_TYPE(dispatchQueue_accessMutex) /* mutex for access to queue */
- pthread_cond_t dispatchQueue_condition; /* so the workers don't spin if the queue is empty */
- UA_LOCK_TYPE(dispatchQueue_conditionMutex) /* mutex for access to condition variable */
-#endif
-
- /* Delayed callbacks
- * To be executed after all curretly dispatched works has finished */
- SIMPLEQ_HEAD(, UA_DelayedCallback) delayedCallbacks;
-#if UA_MULTITHREADING >= 200
- UA_LOCK_TYPE(delayedCallbacks_accessMutex)
- UA_DelayedCallback *delayedCallbacks_checkpoint;
- size_t delayedCallbacks_sinceDispatch; /* How many have been added since we
- * tried to dispatch callbacks? */
-#endif
-};
-
-void UA_WorkQueue_init(UA_WorkQueue *wq);
-
-/* Enqueue a delayed callback. It is executed when all previous work in the
- * queue has been finished. The ``cb`` pointer is freed afterwards. ``cb`` can
- * have a NULL callback that is not executed.
- *
- * This method checks internally if existing delayed work can be moved from the
- * delayed queue to the worker dispatch queue. */
-void UA_WorkQueue_enqueueDelayed(UA_WorkQueue *wq, UA_DelayedCallback *cb);
-
-/* Stop the workers, process all enqueued work in the calling thread, clean up
- * mutexes etc. */
-void UA_WorkQueue_cleanup(UA_WorkQueue *wq);
-
-#if UA_MULTITHREADING >= 200
-
-/* Spin up a number of worker threads that listen on the work queue */
-UA_StatusCode UA_WorkQueue_start(UA_WorkQueue *wq, size_t workersCount);
-
-void UA_WorkQueue_stop(UA_WorkQueue *wq);
-
-/* Enqueue work for the worker threads */
-void UA_WorkQueue_enqueue(UA_WorkQueue *wq, UA_ApplicationCallback cb,
- void *application, void *data);
-
-#else
-
-/* Process all enqueued delayed work. This is not needed when workers are
- * running for the multithreading case. (UA_WorkQueue_cleanup still calls this
- * method during cleanup when the workers are shut down.) */
-void UA_WorkQueue_manuallyProcessDelayed(UA_WorkQueue *wq);
-
+ struct aa_head root; /* The root of the time-sorted tree */
+ struct aa_head idRoot; /* The root of the id-sorted tree */
+ UA_UInt64 idCounter; /* Generate unique identifiers. Identifiers are
+ * always above zero. */
+#if UA_MULTITHREADING >= 100
+ UA_Lock timerMutex;
#endif
-
-_UA_END_DECLS
-
-
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/src/ua_timer.h" ***********************************/
-
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- *
- * Copyright 2017, 2018 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
- * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
- */
-
-
-
-_UA_BEGIN_DECLS
-
-struct UA_TimerEntry;
-typedef struct UA_TimerEntry UA_TimerEntry;
-
-ZIP_HEAD(UA_TimerZip, UA_TimerEntry);
-typedef struct UA_TimerZip UA_TimerZip;
-
-ZIP_HEAD(UA_TimerIdZip, UA_TimerEntry);
-typedef struct UA_TimerIdZip UA_TimerIdZip;
-
-/* Only for a single thread. Protect by a mutex if required. */
-typedef struct {
- UA_TimerZip root; /* The root of the time-sorted zip tree */
- UA_TimerIdZip idRoot; /* The root of the id-sorted zip tree */
- UA_UInt64 idCounter;
} UA_Timer;
-void UA_Timer_init(UA_Timer *t);
+void
+UA_Timer_init(UA_Timer *t);
UA_StatusCode
UA_Timer_addTimedCallback(UA_Timer *t, UA_ApplicationCallback callback,
void *application, void *data, UA_DateTime date,
UA_UInt64 *callbackId);
+/* Add a pre-allocated and pre-filled UA_TimerEntry. This cannot fail. It is
+ * used, for example, for delayed memory reclamation where the data structure
+ * begins with a UA_TimerEntry. */
+void
+UA_Timer_addTimerEntry(UA_Timer *t, UA_TimerEntry *te, UA_UInt64 *callbackId);
+
UA_StatusCode
UA_Timer_addRepeatedCallback(UA_Timer *t, UA_ApplicationCallback callback,
void *application, void *data, UA_Double interval_ms,
+ UA_DateTime *baseTime, UA_TimerPolicy timerPolicy,
UA_UInt64 *callbackId);
-/* Change the callback interval. If this is called from within the callback. The
- * adjustment is made during the next _process call. */
UA_StatusCode
-UA_Timer_changeRepeatedCallbackInterval(UA_Timer *t, UA_UInt64 callbackId,
- UA_Double interval_ms);
+UA_Timer_changeRepeatedCallback(UA_Timer *t, UA_UInt64 callbackId,
+ UA_Double interval_ms, UA_DateTime *baseTime,
+ UA_TimerPolicy timerPolicy);
void
UA_Timer_removeCallback(UA_Timer *t, UA_UInt64 callbackId);
@@ -5046,12 +2135,13 @@ UA_Timer_process(UA_Timer *t, UA_DateTime nowMonotonic,
UA_TimerExecutionCallback executionCallback,
void *executionApplication);
-void UA_Timer_deleteMembers(UA_Timer *t);
+void
+UA_Timer_clear(UA_Timer *t);
_UA_END_DECLS
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/src/server/ua_session.h" ***********************************/
+/**** amalgamated original file "/src/server/ua_session.h" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -5091,23 +2181,41 @@ typedef struct {
UA_ApplicationDescription clientDescription;
UA_String sessionName;
UA_Boolean activated;
- void *sessionHandle; // pointer assigned in userland-callback
+ void *sessionHandle; /* pointer assigned in userland-callback */
UA_NodeId sessionId;
UA_UInt32 maxRequestMessageSize;
UA_UInt32 maxResponseMessageSize;
- UA_Double timeout; // [ms]
+ UA_Double timeout; /* in ms */
UA_DateTime validTill;
UA_ByteString serverNonce;
- UA_UInt16 availableContinuationPoints;
+
+ UA_UInt16 availableContinuationPoints;
ContinuationPoint *continuationPoints;
+
+ size_t paramsSize;
+ UA_KeyValuePair *params;
+
+ /* Localization information */
+ size_t localeIdsSize;
+ UA_String *localeIds;
+
#ifdef UA_ENABLE_SUBSCRIPTIONS
- UA_UInt32 lastSubscriptionId;
- UA_UInt32 lastSeenSubscriptionId;
- LIST_HEAD(UA_ListOfUASubscriptions, UA_Subscription) serverSubscriptions;
- SIMPLEQ_HEAD(UA_ListOfQueuedPublishResponses, UA_PublishResponseEntry) responseQueue;
- UA_UInt32 numSubscriptions;
- UA_UInt32 numPublishReq;
- size_t totalRetransmissionQueueSize; /* Retransmissions of all subscriptions */
+ /* The queue is ordered according to the priority byte (higher bytes come
+ * first). When a late subscription finally publishes, then it is pushed to
+ * the back within the sub-set of subscriptions that has the same priority
+ * (round-robin scheduling). */
+ size_t subscriptionsSize;
+ TAILQ_HEAD(, UA_Subscription) subscriptions;
+
+ size_t responseQueueSize;
+ SIMPLEQ_HEAD(, UA_PublishResponseEntry) responseQueue;
+
+ size_t totalRetransmissionQueueSize; /* Retransmissions of all subscriptions */
+#endif
+
+#ifdef UA_ENABLE_DIAGNOSTICS
+ UA_SessionSecurityDiagnosticsDataType securityDiagnostics;
+ UA_SessionDiagnosticsDataType diagnostics;
#endif
} UA_Session;
@@ -5116,7 +2224,7 @@ typedef struct {
* ----------------- */
void UA_Session_init(UA_Session *session);
-void UA_Session_deleteMembersCleanup(UA_Session *session, UA_Server *server);
+void UA_Session_clear(UA_Session *session, UA_Server *server);
void UA_Session_attachToSecureChannel(UA_Session *session, UA_SecureChannel *channel);
void UA_Session_detachFromSecureChannel(UA_Session *session);
UA_StatusCode UA_Session_generateNonce(UA_Session *session);
@@ -5131,17 +2239,19 @@ void UA_Session_updateLifetime(UA_Session *session);
#ifdef UA_ENABLE_SUBSCRIPTIONS
void
-UA_Session_addSubscription(UA_Server *server,
- UA_Session *session,
- UA_Subscription *newSubscription);
+UA_Session_attachSubscription(UA_Session *session, UA_Subscription *sub);
+
+/* If releasePublishResponses is true and the last subscription is removed, all
+ * outstanding PublishResponse are sent with a StatusCode. But we don't do that
+ * if a Subscription is only detached for modification. */
+void
+UA_Session_detachSubscription(UA_Server *server, UA_Session *session,
+ UA_Subscription *sub, UA_Boolean releasePublishResponses);
UA_Subscription *
UA_Session_getSubscriptionById(UA_Session *session,
UA_UInt32 subscriptionId);
-UA_StatusCode
-UA_Session_deleteSubscription(UA_Server *server, UA_Session *session,
- UA_UInt32 subscriptionId);
void
UA_Session_queuePublishReq(UA_Session *session,
@@ -5161,72 +2271,70 @@ UA_Session_dequeuePublishReq(UA_Session *session);
* zero arguments. So we add a dummy argument that is not printed (%.0s is
* string of length zero). */
-#define UA_LOG_SESSION_INTERNAL(LOGGER, LEVEL, SESSION, MSG, ...) do { \
- UA_String idString = UA_STRING_NULL; \
- UA_NodeId_print(&(SESSION)->sessionId, &idString); \
+#define UA_LOG_SESSION_INTERNAL(LOGGER, LEVEL, SESSION, MSG, ...) \
+ do { \
+ int nameLen = (SESSION) ? (int)(SESSION)->sessionName.length : 0; \
+ const char *nameStr = (SESSION) ? \
+ (const char*)(SESSION)->sessionName.data : NULL; \
+ UA_UInt32 chanId = ((SESSION) && (SESSION)->header.channel) ? \
+ (SESSION)->header.channel->securityToken.channelId : 0; \
UA_LOG_##LEVEL(LOGGER, UA_LOGCATEGORY_SESSION, \
- "Connection %i | SecureChannel %i | Session %.*s | " MSG "%.0s", \
- ((SESSION)->header.channel ? \
- ((SESSION)->header.channel->connection ? \
- (int)((SESSION)->header.channel->connection->sockfd) : 0) : 0), \
- ((SESSION)->header.channel ? \
- (SESSION)->header.channel->securityToken.channelId : 0), \
- (int)idString.length, idString.data, __VA_ARGS__); \
- UA_String_clear(&idString); \
+ "SecureChannel %" PRIu32 " | Session \"%.*s\" | " MSG "%.0s", \
+ chanId, nameLen, nameStr, __VA_ARGS__); \
} while(0)
#if UA_LOGLEVEL <= 100
-#define UA_LOG_TRACE_SESSION(LOGGER, SESSION, ...) \
+# define UA_LOG_TRACE_SESSION(LOGGER, SESSION, ...) \
UA_MACRO_EXPAND(UA_LOG_SESSION_INTERNAL(LOGGER, TRACE, SESSION, __VA_ARGS__, ""))
#else
-#define UA_LOG_TRACE_SESSION(LOGGER, SESSION, ...) do {} while(0)
+# define UA_LOG_TRACE_SESSION(LOGGER, SESSION, ...)
#endif
#if UA_LOGLEVEL <= 200
-#define UA_LOG_DEBUG_SESSION(LOGGER, SESSION, ...) \
+# define UA_LOG_DEBUG_SESSION(LOGGER, SESSION, ...) \
UA_MACRO_EXPAND(UA_LOG_SESSION_INTERNAL(LOGGER, DEBUG, SESSION, __VA_ARGS__, ""))
#else
-#define UA_LOG_DEBUG_SESSION(LOGGER, SESSION, ...) do {} while(0)
+# define UA_LOG_DEBUG_SESSION(LOGGER, SESSION, ...)
#endif
#if UA_LOGLEVEL <= 300
-#define UA_LOG_INFO_SESSION(LOGGER, SESSION, ...) \
+# define UA_LOG_INFO_SESSION(LOGGER, SESSION, ...) \
UA_MACRO_EXPAND(UA_LOG_SESSION_INTERNAL(LOGGER, INFO, SESSION, __VA_ARGS__, ""))
#else
-#define UA_LOG_INFO_SESSION(LOGGER, SESSION, ...) do {} while(0)
+# define UA_LOG_INFO_SESSION(LOGGER, SESSION, ...)
#endif
#if UA_LOGLEVEL <= 400
-#define UA_LOG_WARNING_SESSION(LOGGER, SESSION, ...) \
+# define UA_LOG_WARNING_SESSION(LOGGER, SESSION, ...) \
UA_MACRO_EXPAND(UA_LOG_SESSION_INTERNAL(LOGGER, WARNING, SESSION, __VA_ARGS__, ""))
#else
-#define UA_LOG_WARNING_SESSION(LOGGER, SESSION, ...) do {} while(0)
+# define UA_LOG_WARNING_SESSION(LOGGER, SESSION, ...)
#endif
#if UA_LOGLEVEL <= 500
-#define UA_LOG_ERROR_SESSION(LOGGER, SESSION, ...) \
+# define UA_LOG_ERROR_SESSION(LOGGER, SESSION, ...) \
UA_MACRO_EXPAND(UA_LOG_SESSION_INTERNAL(LOGGER, ERROR, SESSION, __VA_ARGS__, ""))
#else
-#define UA_LOG_ERROR_SESSION(LOGGER, SESSION, ...) do {} while(0)
+# define UA_LOG_ERROR_SESSION(LOGGER, SESSION, ...)
#endif
#if UA_LOGLEVEL <= 600
-#define UA_LOG_FATAL_SESSION(LOGGER, SESSION, ...) \
+# define UA_LOG_FATAL_SESSION(LOGGER, SESSION, ...) \
UA_MACRO_EXPAND(UA_LOG_SESSION_INTERNAL(LOGGER, FATAL, SESSION, __VA_ARGS__, ""))
#else
-#define UA_LOG_FATAL_SESSION(LOGGER, SESSION, ...) do {} while(0)
+# define UA_LOG_FATAL_SESSION(LOGGER, SESSION, ...)
#endif
_UA_END_DECLS
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/src/server/ua_subscription.h" ***********************************/
+/**** amalgamated original file "/src/server/ua_subscription.h" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
- * Copyright 2015-2018 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
+ * Copyright 2015-2018, 2021-2022 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
* Copyright 2015 (c) Chris Iatrou
* Copyright 2015-2016 (c) Sten Grüner
* Copyright 2015 (c) Oleksiy Vasylyev
@@ -5234,6 +2342,8 @@ _UA_END_DECLS
* Copyright 2017 (c) Stefan Profanter, fortiss GmbH
* Copyright 2017 (c) Mattias Bornhager
* Copyright 2019 (c) HMS Industrial Networks AB (Author: Jonas Green)
+ * Copyright 2020 (c) Christian von Arnim, ISW University of Stuttgart (for VDW and umati)
+ * Copyright 2021 (c) Fraunhofer IOSB (Author: Andreas Ebner)
*/
@@ -5243,18 +2353,7 @@ _UA_BEGIN_DECLS
#ifdef UA_ENABLE_SUBSCRIPTIONS
-#define UA_BOUNDEDVALUE_SETWBOUNDS(BOUNDS, SRC, DST) { \
- if(SRC > BOUNDS.max) DST = BOUNDS.max; \
- else if(SRC < BOUNDS.min) DST = BOUNDS.min; \
- else DST = SRC; \
- }
-
-/* Set to the TAILQ_NEXT pointer of a notification, the sentinel that the
- * notification was not added to the global queue */
-#define UA_SUBSCRIPTION_QUEUE_SENTINEL ((UA_Notification*)0x01)
-
-/**
- * MonitoredItems create Notifications. Subscriptions collect Notifications from
+/* MonitoredItems create Notifications. Subscriptions collect Notifications from
* (several) MonitoredItems and publish them to the client.
*
* Notifications are put into two queues at the same time. One for the
@@ -5262,200 +2361,194 @@ _UA_BEGIN_DECLS
* space reserved for the MonitoredItem runs full. The second queue is the
* "global" queue for all Notifications generated in a Subscription. For
* publication, the notifications are taken out of the "global" queue in the
- * order of their creation.
- */
+ * order of their creation. */
/*****************/
-/* MonitoredItem */
+/* Notifications */
/*****************/
-struct UA_MonitoredItem;
-typedef struct UA_MonitoredItem UA_MonitoredItem;
-
-#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
-
-typedef struct UA_EventNotification {
- UA_EventFieldList fields;
- /* EventFilterResult currently isn't being used
- UA_EventFilterResult result; */
-} UA_EventNotification;
-
-#ifdef UA_ENABLE_SUBSCRIPTIONS_ALARMS_CONDITIONS
-
-typedef enum {
- UA_INACTIVE,
- UA_ACTIVE,
- UA_ACTIVE_HIGHHIGH,
- UA_ACTIVE_HIGH,
- UA_ACTIVE_LOW,
- UA_ACTIVE_LOWLOW
-} UA_ActiveState;
-
-typedef struct {
- UA_TwoStateVariableChangeCallback enableStateCallback;
- UA_TwoStateVariableChangeCallback ackStateCallback;
- UA_Boolean ackedRemoveBranch;
- UA_TwoStateVariableChangeCallback confirmStateCallback;
- UA_Boolean confirmedRemoveBranch;
- UA_TwoStateVariableChangeCallback activeStateCallback;
-} UA_ConditionCallbacks;
-
-/*
- * In Alarms and Conditions first implementation, conditionBranchId
- * is always equal to NULL NodeId (UA_NODEID_NULL). That ConditionBranch
- * represents the current state Condition. The current state is determined
- * by the last Event triggered (lastEventId). See Part 9, 5.5.2, BranchId.
- */
-typedef struct UA_ConditionBranch {
- LIST_ENTRY(UA_ConditionBranch) listEntry;
- UA_NodeId conditionBranchId;
- UA_ByteString lastEventId;
- UA_Boolean isCallerAC;
-} UA_ConditionBranch;
-
-/*
- * In Alarms and Conditions first implementation, A Condition
- * have only one ConditionBranch entry.
- */
-typedef struct UA_Condition {
- LIST_ENTRY(UA_Condition) listEntry;
- LIST_HEAD(, UA_ConditionBranch) conditionBranchHead;
- UA_NodeId conditionId;
- UA_UInt16 lastSeverity;
- UA_DateTime lastSeveritySourceTimeStamp;
- UA_ConditionCallbacks callbacks;
- UA_ActiveState lastActiveState;
- UA_ActiveState currentActiveState;
- UA_Boolean isLimitAlarm;
-} UA_Condition;
-
-/*
- * A ConditionSource can have multiple Conditions.
- */
-typedef struct UA_ConditionSource {
- LIST_ENTRY(UA_ConditionSource) listEntry;
- LIST_HEAD(, UA_Condition) conditionHead;
- UA_NodeId conditionSourceId;
-} UA_ConditionSource;
-
-#endif /* UA_ENABLE_SUBSCRIPTIONS_ALARMS_CONDITIONS */
-
-#endif /* UA_ENABLE_SUBSCRIPTIONS_EVENTS */
+/* Set to the TAILQ_NEXT pointer of a notification, the sentinel that the
+ * notification was not added to the global queue */
+#define UA_SUBSCRIPTION_QUEUE_SENTINEL ((UA_Notification*)0x01)
typedef struct UA_Notification {
- TAILQ_ENTRY(UA_Notification) listEntry; /* Notification list for the MonitoredItem */
+ TAILQ_ENTRY(UA_Notification) localEntry; /* Notification list for the MonitoredItem */
TAILQ_ENTRY(UA_Notification) globalEntry; /* Notification list for the Subscription */
+ UA_MonitoredItem *mon; /* Always set */
- UA_MonitoredItem *mon;
-
- /* See the monitoredItemType of the MonitoredItem */
+ /* The event field is used if mon->attributeId is the EventNotifier */
union {
+ UA_MonitoredItemNotification dataChange;
#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
- UA_EventNotification event;
+ UA_EventFieldList event;
#endif
- UA_DataValue value;
} data;
-} UA_Notification;
-/* Ensure enough space is available; Add notification to the linked lists;
- * Increase the counters */
-void UA_Notification_enqueue(UA_Server *server, UA_Subscription *sub,
- UA_MonitoredItem *mon, UA_Notification *n);
+#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
+ UA_Boolean isOverflowEvent; /* Counted manually */
+ UA_EventFilterResult result;
+#endif
+} UA_Notification;
-/* Remove the notification from the MonitoredItem's queue and the Subscriptions
- * global queue. Reduce the respective counters. */
-void UA_Notification_dequeue(UA_Server *server, UA_Notification *n);
+/* Initializes and sets the sentinel pointers */
+UA_Notification * UA_Notification_new(void);
-/* Delete the notification. Must be dequeued first. */
+/* Notifications are always added to the queue of the MonitoredItem. That queue
+ * can overflow. If Notifications are reported, they are also added to the
+ * global queue of the Subscription. There they are picked up by the publishing
+ * callback.
+ *
+ * There are two ways Notifications can be put into the global queue of the
+ * Subscription: They are added because the MonitoringMode of the MonitoredItem
+ * is "reporting". Or the MonitoringMode is "sampling" and a link is trigered
+ * that puts the last Notification into the global queue. */
+void UA_Notification_enqueueAndTrigger(UA_Server *server,
+ UA_Notification *n);
+
+/* Dequeue and delete the notification */
void UA_Notification_delete(UA_Notification *n);
+/* A NotificationMessage contains an array of notifications.
+ * Sent NotificationMessages are stored for the republish service. */
+typedef struct UA_NotificationMessageEntry {
+ TAILQ_ENTRY(UA_NotificationMessageEntry) listEntry;
+ UA_NotificationMessage message;
+} UA_NotificationMessageEntry;
+
+/* Queue Definitions */
typedef TAILQ_HEAD(NotificationQueue, UA_Notification) NotificationQueue;
+typedef TAILQ_HEAD(NotificationMessageQueue, UA_NotificationMessageEntry)
+ NotificationMessageQueue;
+
+/*****************/
+/* MonitoredItem */
+/*****************/
struct UA_MonitoredItem {
- UA_DelayedCallback delayedFreePointers;
- LIST_ENTRY(UA_MonitoredItem) listEntry;
- UA_Subscription *subscription; /* Local MonitoredItem if the subscription is NULL */
+ UA_TimerEntry delayedFreePointers;
+ LIST_ENTRY(UA_MonitoredItem) listEntry; /* Linked list in the Subscription */
+ UA_MonitoredItem *next; /* Linked list of MonitoredItems directly attached
+ * to a Node. Initialized to ~0 to indicate that the
+ * MonitoredItem is not added to a node. */
+ UA_Subscription *subscription; /* If NULL, then this is a Local MonitoredItem */
UA_UInt32 monitoredItemId;
- UA_UInt32 clientHandle;
- UA_Boolean registered; /* Was the MonitoredItem registered in Userland with
- the callback? */
- /* Settings */
- UA_TimestampsToReturn timestampsToReturn;
+ /* Status and Settings */
+ UA_ReadValueId itemToMonitor;
UA_MonitoringMode monitoringMode;
- UA_NodeId monitoredNodeId;
- UA_UInt32 attributeId;
- UA_String indexRange;
- UA_Double samplingInterval; // [ms]
- UA_Boolean discardOldest;
- union {
-#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
- /* If attributeId == UA_ATTRIBUTEID_EVENTNOTIFIER */
- UA_EventFilter eventFilter;
-#endif
- /* The DataChangeFilter always contains an absolute deadband definition.
- * Part 8, §6.2 gives the following formula to test for percentage
- * deadbands:
- *
- * DataChange if (absolute value of (last cached value - current value)
- * > (deadbandValue/100.0) * ((high–low) of EURange)))
- *
- * So we can convert from a percentage to an absolute deadband and keep
- * the hot code path simple.
- *
- * TODO: Store the percentage deadband to recompute when the UARange is
- * changed at runtime of the MonitoredItem */
- UA_DataChangeFilter dataChangeFilter;
- } filter;
- UA_Variant lastValue; // TODO: dataEncoding is hardcoded to UA binary
+ UA_TimestampsToReturn timestampsToReturn;
+ UA_Boolean sampleCallbackIsRegistered;
+ UA_Boolean registered; /* Registered in the server / Subscription */
+ UA_DateTime triggeredUntil; /* If the MonitoringMode is SAMPLING,
+ * triggering the MonitoredItem puts the latest
+ * Notification into the publishing queue (of
+ * the Subscription). In addition, the first
+ * new sample is also published (and not just
+ * sampled) if it occurs within the duration of
+ * one publishing cycle after the triggering. */
+
+ /* If the filter is a UA_DataChangeFilter: The DataChangeFilter always
+ * contains an absolute deadband definition. Part 8, §6.2 gives the
+ * following formula to test for percentage deadbands:
+ *
+ * DataChange if (absolute value of (last cached value - current value)
+ * > (deadbandValue/100.0) * ((high–low) of EURange)))
+ *
+ * So we can convert from a percentage to an absolute deadband and keep
+ * the hot code path simple.
+ *
+ * TODO: Store the percentage deadband to recompute when the UARange is
+ * changed at runtime of the MonitoredItem */
+ UA_MonitoringParameters parameters;
- /* Sample Callback */
+ /* Sampling Callback */
UA_UInt64 sampleCallbackId;
- UA_ByteString lastSampledValue;
- UA_Boolean sampleCallbackIsRegistered;
+ UA_DataValue lastValue;
+
+ /* Triggering Links */
+ size_t triggeringLinksSize;
+ UA_UInt32 *triggeringLinks;
/* Notification Queue */
NotificationQueue queue;
- UA_UInt32 maxQueueSize; /* The max number of enqueued notifications (not
- * counting overflow events) */
- UA_UInt32 queueSize;
- UA_UInt32 eventOverflows; /* Separate counter for the queue. Can at most
- * double the queue size */
+ size_t queueSize; /* This is the current size. See also the configured
+ * (maximum) queueSize in the parameters. */
+ size_t eventOverflows; /* Separate counter for the queue. Can at most double
+ * the queue size */
+};
-#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
- UA_MonitoredItem *next;
-#endif
+void UA_MonitoredItem_init(UA_MonitoredItem *mon);
-#ifdef UA_ENABLE_DA
- UA_StatusCode lastStatus;
-#endif
-};
+void
+UA_MonitoredItem_delete(UA_Server *server, UA_MonitoredItem *monitoredItem);
-void UA_MonitoredItem_init(UA_MonitoredItem *mon, UA_Subscription *sub);
-void UA_MonitoredItem_delete(UA_Server *server, UA_MonitoredItem *monitoredItem);
-void UA_MonitoredItem_sampleCallback(UA_Server *server, UA_MonitoredItem *monitoredItem);
-UA_StatusCode UA_MonitoredItem_registerSampleCallback(UA_Server *server, UA_MonitoredItem *mon);
-void UA_MonitoredItem_unregisterSampleCallback(UA_Server *server, UA_MonitoredItem *mon);
+void
+UA_MonitoredItem_removeOverflowInfoBits(UA_MonitoredItem *mon);
+
+void
+UA_Server_registerMonitoredItem(UA_Server *server, UA_MonitoredItem *mon);
-UA_StatusCode UA_Event_addEventToMonitoredItem(UA_Server *server, const UA_NodeId *event, UA_MonitoredItem *mon);
-UA_StatusCode UA_Event_generateEventId(UA_ByteString *generatedId);
+/* Register sampling. Either by adding a repeated callback or by adding the
+ * MonitoredItem to a linked list in the node. */
+UA_StatusCode
+UA_MonitoredItem_registerSampling(UA_Server *server, UA_MonitoredItem *mon);
+
+void
+UA_MonitoredItem_unregisterSampling(UA_Server *server,
+ UA_MonitoredItem *mon);
+
+UA_StatusCode
+UA_MonitoredItem_setMonitoringMode(UA_Server *server, UA_MonitoredItem *mon,
+ UA_MonitoringMode monitoringMode);
+
+void
+UA_MonitoredItem_sampleCallback(UA_Server *server,
+ UA_MonitoredItem *monitoredItem);
+
+UA_StatusCode
+sampleCallbackWithValue(UA_Server *server, UA_Subscription *sub,
+ UA_MonitoredItem *mon, UA_DataValue *value);
+
+UA_StatusCode
+UA_MonitoredItem_removeLink(UA_Subscription *sub, UA_MonitoredItem *mon,
+ UA_UInt32 linkId);
+
+UA_StatusCode
+UA_MonitoredItem_addLink(UA_Subscription *sub, UA_MonitoredItem *mon,
+ UA_UInt32 linkId);
+
+UA_StatusCode
+UA_MonitoredItem_createDataChangeNotification(UA_Server *server,
+ UA_Subscription *sub,
+ UA_MonitoredItem *mon,
+ const UA_DataValue *value);
+
+UA_StatusCode
+UA_Event_addEventToMonitoredItem(UA_Server *server, const UA_NodeId *event,
+ UA_MonitoredItem *mon);
+
+UA_StatusCode
+UA_Event_generateEventId(UA_ByteString *generatedId);
+
+void
+UA_Event_staticSelectClauseValidation(UA_Server *server,
+ const UA_EventFilter *eventFilter,
+ UA_StatusCode *result);
+
+UA_StatusCode
+UA_Event_staticWhereClauseValidation(UA_Server *server,
+ const UA_ContentFilter *filter,
+ UA_ContentFilterResult *);
/* Remove entries until mon->maxQueueSize is reached. Sets infobits for lost
* data if required. */
-UA_StatusCode UA_MonitoredItem_ensureQueueSpace(UA_Server *server, UA_MonitoredItem *mon);
-
-UA_StatusCode UA_MonitoredItem_removeNodeEventCallback(UA_Server *server, UA_Session *session,
- UA_Node *node, void *data);
+void
+UA_MonitoredItem_ensureQueueSpace(UA_Server *server, UA_MonitoredItem *mon);
/****************/
/* Subscription */
/****************/
-typedef struct UA_NotificationMessageEntry {
- TAILQ_ENTRY(UA_NotificationMessageEntry) listEntry;
- UA_NotificationMessage message;
-} UA_NotificationMessageEntry;
-
/* We use only a subset of the states defined in the standard */
typedef enum {
/* UA_SUBSCRIPTIONSTATE_CLOSED */
@@ -5465,12 +2558,18 @@ typedef enum {
UA_SUBSCRIPTIONSTATE_KEEPALIVE
} UA_SubscriptionState;
-typedef TAILQ_HEAD(ListOfNotificationMessages, UA_NotificationMessageEntry) ListOfNotificationMessages;
-
+/* Subscriptions are managed in a server-wide linked list. If they are attached
+ * to a Session, then they are additionaly in the per-Session linked-list. A
+ * subscription is always generated for a Session. But the CloseSession Service
+ * may keep Subscriptions intact beyond the Session lifetime. They can then be
+ * re-bound to a new Session with the TransferSubscription Service. */
struct UA_Subscription {
- UA_DelayedCallback delayedFreePointers;
- LIST_ENTRY(UA_Subscription) listEntry;
- UA_Session *session;
+ UA_TimerEntry delayedFreePointers;
+ LIST_ENTRY(UA_Subscription) serverListEntry;
+ /* Ordered according to the priority byte and round-robin scheduling for
+ * late subscriptions. See ua_session.h. Only set if session != NULL. */
+ TAILQ_ENTRY(UA_Subscription) sessionListEntry;
+ UA_Session *session; /* May be NULL if no session is attached. */
UA_UInt32 subscriptionId;
/* Settings */
@@ -5479,17 +2578,19 @@ struct UA_Subscription {
UA_Double publishingInterval; /* in ms */
UA_UInt32 notificationsPerPublish;
UA_Boolean publishingEnabled;
- UA_UInt32 priority;
+ UA_Byte priority;
/* Runtime information */
UA_SubscriptionState state;
+ UA_StatusCode statusChange; /* If set, a notification is generated and the
+ * Subscription is deleted within
+ * UA_Subscription_publish. */
UA_UInt32 nextSequenceNumber;
UA_UInt32 currentKeepAliveCount;
UA_UInt32 currentLifetimeCount;
- /* Publish Callback */
+ /* Publish Callback. Registered if id > 0. */
UA_UInt64 publishCallbackId;
- UA_Boolean publishCallbackIsRegistered;
/* MonitoredItems */
UA_UInt32 lastMonitoredItemId; /* increase the identifiers */
@@ -5497,56 +2598,151 @@ struct UA_Subscription {
UA_UInt32 monitoredItemsSize;
/* Global list of notifications from the MonitoredItems */
- NotificationQueue notificationQueue;
+ TAILQ_HEAD(, UA_Notification) notificationQueue;
UA_UInt32 notificationQueueSize; /* Total queue size */
UA_UInt32 dataChangeNotifications;
UA_UInt32 eventNotifications;
- UA_UInt32 statusChangeNotifications;
-
- /* Notifications to be sent out now (already late). In a regular publish
- * callback, all queued notifications are sent out. In a late publish
- * response, only the notifications left from the last regular publish
- * callback are sent. */
- UA_UInt32 readyNotifications;
/* Retransmission Queue */
- ListOfNotificationMessages retransmissionQueue;
+ NotificationMessageQueue retransmissionQueue;
size_t retransmissionQueueSize;
+
+ /* Statistics for the server diagnostics. The fields are defined according
+ * to the SubscriptionDiagnosticsDataType (Part 5, §12.15). */
+#ifdef UA_ENABLE_DIAGNOSTICS
+ UA_UInt32 modifyCount;
+ UA_UInt32 enableCount;
+ UA_UInt32 disableCount;
+ UA_UInt32 republishRequestCount;
+ UA_UInt32 republishMessageCount;
+ UA_UInt32 transferRequestCount;
+ UA_UInt32 transferredToAltClientCount;
+ UA_UInt32 transferredToSameClientCount;
+ UA_UInt32 publishRequestCount;
+ UA_UInt32 dataChangeNotificationsCount;
+ UA_UInt32 eventNotificationsCount;
+ UA_UInt32 notificationsCount;
+ UA_UInt32 latePublishRequestCount;
+ UA_UInt32 discardedMessageCount;
+ UA_UInt32 monitoringQueueOverflowCount;
+ UA_UInt32 eventQueueOverFlowCount;
+#endif
};
-UA_Subscription * UA_Subscription_new(UA_Session *session, UA_UInt32 subscriptionId);
-void UA_Subscription_deleteMembers(UA_Server *server, UA_Subscription *sub);
-UA_StatusCode Subscription_registerPublishCallback(UA_Server *server, UA_Subscription *sub);
-void Subscription_unregisterPublishCallback(UA_Server *server, UA_Subscription *sub);
-void UA_Subscription_addMonitoredItem(UA_Server *server, UA_Subscription *sub, UA_MonitoredItem *newMon);
-UA_MonitoredItem * UA_Subscription_getMonitoredItem(UA_Subscription *sub, UA_UInt32 monitoredItemId);
+UA_Subscription * UA_Subscription_new(void);
+
+void
+UA_Subscription_delete(UA_Server *server, UA_Subscription *sub);
UA_StatusCode
-UA_Subscription_deleteMonitoredItem(UA_Server *server, UA_Subscription *sub,
- UA_UInt32 monitoredItemId);
+Subscription_registerPublishCallback(UA_Server *server,
+ UA_Subscription *sub);
-void UA_Subscription_publish(UA_Server *server, UA_Subscription *sub);
-UA_StatusCode UA_Subscription_removeRetransmissionMessage(UA_Subscription *sub,
- UA_UInt32 sequenceNumber);
-void UA_Subscription_answerPublishRequestsNoSubscription(UA_Server *server, UA_Session *session);
-UA_Boolean UA_Subscription_reachedPublishReqLimit(UA_Server *server, UA_Session *session);
+void
+Subscription_unregisterPublishCallback(UA_Server *server,
+ UA_Subscription *sub);
-#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
+UA_MonitoredItem *
+UA_Subscription_getMonitoredItem(UA_Subscription *sub,
+ UA_UInt32 monitoredItemId);
+
+void
+UA_Subscription_publish(UA_Server *server, UA_Subscription *sub);
-/* Only for unit testing */
UA_StatusCode
-UA_Server_evaluateWhereClauseContentFilter(
- UA_Server *server,
- const UA_NodeId *eventNode,
- const UA_ContentFilter *contentFilter);
-#endif /* UA_ENABLE_SUBSCRIPTIONS_EVENTS */
+UA_Subscription_removeRetransmissionMessage(UA_Subscription *sub,
+ UA_UInt32 sequenceNumber);
+
+UA_Boolean
+UA_Session_reachedPublishReqLimit(UA_Server *server, UA_Session *session);
+
+/* Forward declaration for A&C used in ua_server_internal.h" */
+struct UA_ConditionSource;
+typedef struct UA_ConditionSource UA_ConditionSource;
+
+/***********/
+/* Helpers */
+/***********/
+
+/* Evaluate content filter, Only for unit testing */
+#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
+UA_StatusCode
+UA_Server_evaluateWhereClauseContentFilter(UA_Server *server, UA_Session *session,
+ const UA_NodeId *eventNode,
+ const UA_ContentFilter *contentFilter,
+ UA_ContentFilterResult *contentFilterResult);
+#endif
+
+/* Setting an integer value within bounds */
+#define UA_BOUNDEDVALUE_SETWBOUNDS(BOUNDS, SRC, DST) { \
+ if(SRC > BOUNDS.max) DST = BOUNDS.max; \
+ else if(SRC < BOUNDS.min) DST = BOUNDS.min; \
+ else DST = SRC; \
+ }
+
+/* Logging
+ * See a description of the tricks used in ua_session.h */
+#define UA_LOG_SUBSCRIPTION_INTERNAL(LOGGER, LEVEL, SUB, MSG, ...) \
+ do { \
+ if((SUB) && (SUB)->session) { \
+ UA_LOG_##LEVEL##_SESSION(LOGGER, (SUB)->session, \
+ "Subscription %" PRIu32 " | " MSG "%.0s", \
+ (SUB)->subscriptionId, __VA_ARGS__); \
+ } else { \
+ UA_LOG_##LEVEL(LOGGER, UA_LOGCATEGORY_SERVER, \
+ "Subscription %" PRIu32 " | " MSG "%.0s", \
+ (SUB) ? (SUB)->subscriptionId : 0, __VA_ARGS__); \
+ } \
+ } while(0)
+
+#if UA_LOGLEVEL <= 100
+# define UA_LOG_TRACE_SUBSCRIPTION(LOGGER, SUB, ...) \
+ UA_MACRO_EXPAND(UA_LOG_SUBSCRIPTION_INTERNAL(LOGGER, TRACE, SUB, __VA_ARGS__, ""))
+#else
+# define UA_LOG_TRACE_SUBSCRIPTION(LOGGER, SUB, ...) do {} while(0)
+#endif
+
+#if UA_LOGLEVEL <= 200
+# define UA_LOG_DEBUG_SUBSCRIPTION(LOGGER, SUB, ...) \
+ UA_MACRO_EXPAND(UA_LOG_SUBSCRIPTION_INTERNAL(LOGGER, DEBUG, SUB, __VA_ARGS__, ""))
+#else
+# define UA_LOG_DEBUG_SUBSCRIPTION(LOGGER, SUB, ...) do {} while(0)
+#endif
+
+#if UA_LOGLEVEL <= 300
+# define UA_LOG_INFO_SUBSCRIPTION(LOGGER, SUB, ...) \
+ UA_MACRO_EXPAND(UA_LOG_SUBSCRIPTION_INTERNAL(LOGGER, INFO, SUB, __VA_ARGS__, ""))
+#else
+# define UA_LOG_INFO_SUBSCRIPTION(LOGGER, SUB, ...) do {} while(0)
+#endif
+
+#if UA_LOGLEVEL <= 400
+# define UA_LOG_WARNING_SUBSCRIPTION(LOGGER, SUB, ...) \
+ UA_MACRO_EXPAND(UA_LOG_SUBSCRIPTION_INTERNAL(LOGGER, WARNING, SUB, __VA_ARGS__, ""))
+#else
+# define UA_LOG_WARNING_SUBSCRIPTION(LOGGER, SUB, ...) do {} while(0)
+#endif
+
+#if UA_LOGLEVEL <= 500
+# define UA_LOG_ERROR_SUBSCRIPTION(LOGGER, SUB, ...) \
+ UA_MACRO_EXPAND(UA_LOG_SUBSCRIPTION_INTERNAL(LOGGER, ERROR, SUB, __VA_ARGS__, ""))
+#else
+# define UA_LOG_ERROR_SUBSCRIPTION(LOGGER, SUB, ...) do {} while(0)
+#endif
+
+#if UA_LOGLEVEL <= 600
+# define UA_LOG_FATAL_SUBSCRIPTION(LOGGER, SUB, ...) \
+ UA_MACRO_EXPAND(UA_LOG_SUBSCRIPTION_INTERNAL(LOGGER, FATAL, SUB, __VA_ARGS__, ""))
+#else
+# define UA_LOG_FATAL_SUBSCRIPTION(LOGGER, SUB, ...) do {} while(0)
+#endif
#endif /* UA_ENABLE_SUBSCRIPTIONS */
_UA_END_DECLS
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/src/pubsub/ua_pubsub_networkmessage.h" ***********************************/
+/**** amalgamated original file "/src/pubsub/ua_pubsub_networkmessage.h" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -5568,16 +2764,17 @@ typedef struct {
/* FieldEncoding Enum */
typedef enum {
- UA_FIELDENCODING_VARIANT = 0,
+ UA_FIELDENCODING_VARIANT = 0,
UA_FIELDENCODING_RAWDATA = 1,
- UA_FIELDENCODING_DATAVALUE = 2
+ UA_FIELDENCODING_DATAVALUE = 2,
+ UA_FIELDENCODING_UNKNOWN = 3
} UA_FieldEncoding;
/* DataSetMessage Type */
typedef enum {
UA_DATASETMESSAGE_DATAKEYFRAME = 0,
UA_DATASETMESSAGE_DATADELTAFRAME = 1,
- UA_DATASETMESSAGE_EVENT = 2,
+ UA_DATASETMESSAGE_EVENT = 2,
UA_DATASETMESSAGE_KEEPALIVE = 3
} UA_DataSetMessageType;
@@ -5600,52 +2797,6 @@ typedef struct {
UA_UInt32 configVersionMinorVersion;
} UA_DataSetMessageHeader;
-UA_StatusCode
-UA_DataSetMessageHeader_encodeBinary(const UA_DataSetMessageHeader* src,
- UA_Byte **bufPos, const UA_Byte *bufEnd);
-
-UA_StatusCode
-UA_DataSetMessageHeader_decodeBinary(const UA_ByteString *src, size_t *offset,
- UA_DataSetMessageHeader* dst);
-
-size_t
-UA_DataSetMessageHeader_calcSizeBinary(const UA_DataSetMessageHeader* p);
-
-/**********************************************/
-/* Network Message Offsets */
-/**********************************************/
-
-/* Offsets for buffered messages in the PubSub fast path. */
-typedef enum {
- UA_PUBSUB_OFFSETTYPE_DATASETMESSAGE_SEQUENCENUMBER,
- UA_PUBSUB_OFFSETTYPE_NETWORKMESSAGE_SEQUENCENUMBER,
- UA_PUBSUB_OFFSETTYPE_TIMESTAMP_PICOSECONDS,
- UA_PUBSUB_OFFSETTYPE_TIMESTAMP, /* source pointer */
- UA_PUBSUB_OFFSETTYPE_TIMESTAMP_NOW, /* no source */
- UA_PUBSUB_OFFSETTYPE_PAYLOAD_DATAVALUE,
- UA_PUBSUB_OFFSETTYPE_PAYLOAD_VARIANT,
- UA_PUBSUB_OFFSETTYPE_PAYLOAD_RAW
- /* Add more offset types as needed */
-} UA_NetworkMessageOffsetType;
-
-typedef struct {
- UA_NetworkMessageOffsetType contentType;
- union {
- union {
- UA_DataValue *value;
- size_t valueBinarySize;
- } value;
- UA_DateTime *timestamp;
- } offsetData;
- size_t offset;
-} UA_NetworkMessageOffset;
-
-typedef struct {
- UA_ByteString buffer; /* The precomputed message buffer */
- UA_NetworkMessageOffset *offsets; /* Offsets for changes in the message buffer */
- size_t offsetsSize;
-} UA_NetworkMessageOffsetBuffer;
-
/**
* DataSetMessage
* ^^^^^^^^^^^^^^ */
@@ -5653,6 +2804,7 @@ typedef struct {
typedef struct {
UA_UInt16 fieldCount;
UA_DataValue* dataSetFields;
+ UA_ByteString rawFields;
/* Json keys for the dataSetFields: TODO: own dataSetMessageType for json? */
UA_String* fieldNames;
} UA_DataSetMessage_DataKeyFrameData;
@@ -5675,20 +2827,6 @@ typedef struct {
} data;
} UA_DataSetMessage;
-UA_StatusCode
-UA_DataSetMessage_encodeBinary(const UA_DataSetMessage* src, UA_Byte **bufPos,
- const UA_Byte *bufEnd);
-
-UA_StatusCode
-UA_DataSetMessage_decodeBinary(const UA_ByteString *src, size_t *offset,
- UA_DataSetMessage* dst);
-
-size_t
-UA_DataSetMessage_calcSizeBinary(UA_DataSetMessage *p, UA_NetworkMessageOffsetBuffer *offsetBuffer,
- size_t currentOffset);
-
-void UA_DataSetMessage_free(const UA_DataSetMessage* p);
-
typedef struct {
UA_UInt16* sizes;
UA_DataSetMessage* dataSetMessages;
@@ -5731,7 +2869,6 @@ typedef struct {
UA_Boolean securityFooterEnabled;
UA_Boolean forceKeyReset;
UA_UInt32 securityTokenId; // spec: IntegerId
- UA_Byte nonceLength;
UA_ByteString messageNonce;
UA_UInt16 securityFooterSize;
} UA_NetworkMessageSecurityHeader;
@@ -5782,27 +2919,151 @@ typedef struct {
} payload;
UA_ByteString securityFooter;
- UA_ByteString signature;
} UA_NetworkMessage;
+/**********************************************/
+/* Network Message Offsets */
+/**********************************************/
+
+/* Offsets for buffered messages in the PubSub fast path. */
+typedef enum {
+ UA_PUBSUB_OFFSETTYPE_DATASETMESSAGE_SEQUENCENUMBER,
+ UA_PUBSUB_OFFSETTYPE_NETWORKMESSAGE_SEQUENCENUMBER,
+ UA_PUBSUB_OFFSETTYPE_NETWORKMESSAGE_FIELDENCDODING,
+ UA_PUBSUB_OFFSETTYPE_TIMESTAMP_PICOSECONDS,
+ UA_PUBSUB_OFFSETTYPE_TIMESTAMP, /* source pointer */
+ UA_PUBSUB_OFFSETTYPE_TIMESTAMP_NOW, /* no source */
+ UA_PUBSUB_OFFSETTYPE_PAYLOAD_DATAVALUE,
+ UA_PUBSUB_OFFSETTYPE_PAYLOAD_VARIANT,
+ UA_PUBSUB_OFFSETTYPE_PAYLOAD_RAW,
+ /* For subscriber RT */
+ UA_PUBSUB_OFFSETTYPE_PUBLISHERID,
+ UA_PUBSUB_OFFSETTYPE_WRITERGROUPID,
+ UA_PUBSUB_OFFSETTYPE_DATASETWRITERID
+ /* Add more offset types as needed */
+} UA_NetworkMessageOffsetType;
+
+typedef struct {
+ UA_NetworkMessageOffsetType contentType;
+ union {
+ struct {
+ UA_DataValue *value;
+ size_t valueBinarySize;
+ } value;
+ UA_DateTime *timestamp;
+ } offsetData;
+ size_t offset;
+} UA_NetworkMessageOffset;
+
+typedef struct {
+ UA_ByteString buffer; /* The precomputed message buffer */
+ UA_NetworkMessageOffset *offsets; /* Offsets for changes in the message buffer */
+ size_t offsetsSize;
+ UA_Boolean RTsubscriberEnabled; /* Addtional offsets computation like publisherId, WGId if this bool enabled */
+ UA_NetworkMessage *nm; /* The precomputed NetworkMessage for subscriber */
+ size_t rawMessageLength;
+} UA_NetworkMessageOffsetBuffer;
+
+/**
+ * DataSetMessage
+ * ^^^^^^^^^^^^^^ */
+
+UA_StatusCode
+UA_DataSetMessageHeader_encodeBinary(const UA_DataSetMessageHeader* src,
+ UA_Byte **bufPos, const UA_Byte *bufEnd);
+
+UA_StatusCode
+UA_DataSetMessageHeader_decodeBinary(const UA_ByteString *src, size_t *offset,
+ UA_DataSetMessageHeader* dst);
+
+size_t
+UA_DataSetMessageHeader_calcSizeBinary(const UA_DataSetMessageHeader* p);
+
+UA_StatusCode
+UA_DataSetMessage_encodeBinary(const UA_DataSetMessage* src, UA_Byte **bufPos,
+ const UA_Byte *bufEnd);
+
+UA_StatusCode
+UA_DataSetMessage_decodeBinary(const UA_ByteString *src, size_t *offset,
+ UA_DataSetMessage* dst, UA_UInt16 dsmSize);
+
+size_t
+UA_DataSetMessage_calcSizeBinary(UA_DataSetMessage *p, UA_NetworkMessageOffsetBuffer *offsetBuffer,
+ size_t currentOffset);
+
+void UA_DataSetMessage_clear(const UA_DataSetMessage* p);
+
+/**
+ * NetworkMessage
+ * ^^^^^^^^^^^^^^ */
+
UA_StatusCode
UA_NetworkMessage_updateBufferedMessage(UA_NetworkMessageOffsetBuffer *buffer);
UA_StatusCode
+UA_NetworkMessage_updateBufferedNwMessage(UA_NetworkMessageOffsetBuffer *buffer,
+ const UA_ByteString *src, size_t *bufferPosition);
+
+
+/**
+ * NetworkMessage Encoding
+ * ^^^^^^^^^^^^^^^^^^^^^^^ */
+
+/* If dataToEncryptStart not-NULL, then it will be set to the start-position of
+ * the payload in the buffer. */
+UA_StatusCode
UA_NetworkMessage_encodeBinary(const UA_NetworkMessage* src,
+ UA_Byte **bufPos, const UA_Byte *bufEnd,
+ UA_Byte **dataToEncryptStart);
+
+UA_StatusCode
+UA_NetworkMessage_encodeHeaders(const UA_NetworkMessage* src,
+ UA_Byte **bufPos, const UA_Byte *bufEnd);
+
+UA_StatusCode
+UA_NetworkMessage_encodePayload(const UA_NetworkMessage* src,
+ UA_Byte **bufPos, const UA_Byte *bufEnd);
+
+UA_StatusCode
+UA_NetworkMessage_encodeFooters(const UA_NetworkMessage* src,
UA_Byte **bufPos, const UA_Byte *bufEnd);
+/**
+ * NetworkMessage Decoding
+ * ^^^^^^^^^^^^^^^^^^^^^^^ */
+
+UA_StatusCode
+UA_NetworkMessage_decodeHeaders(const UA_ByteString *src, size_t *offset, UA_NetworkMessage *dst);
+
+UA_StatusCode
+UA_NetworkMessage_decodePayload(const UA_ByteString *src, size_t *offset, UA_NetworkMessage *dst);
+
+UA_StatusCode
+UA_NetworkMessage_decodeFooters(const UA_ByteString *src, size_t *offset, UA_NetworkMessage *dst);
+
UA_StatusCode
UA_NetworkMessage_decodeBinary(const UA_ByteString *src, size_t *offset,
UA_NetworkMessage* dst);
+
+UA_StatusCode
+UA_NetworkMessageHeader_decodeBinary(const UA_ByteString *src, size_t *offset, UA_NetworkMessage *dst);
+
size_t
-UA_NetworkMessage_calcSizeBinary(UA_NetworkMessage *p, UA_NetworkMessageOffsetBuffer *offsetBuffer);
+UA_NetworkMessage_calcSizeBinary(UA_NetworkMessage *p,
+ UA_NetworkMessageOffsetBuffer *offsetBuffer);
-void
-UA_NetworkMessage_deleteMembers(UA_NetworkMessage* p);
+#ifdef UA_ENABLE_PUBSUB_ENCRYPTION
-#define UA_NetworkMessage_clear(p) UA_NetworkMessage_deleteMembers(p)
+UA_StatusCode
+UA_NetworkMessage_signEncrypt(UA_NetworkMessage *nm, UA_MessageSecurityMode securityMode,
+ UA_PubSubSecurityPolicy *policy, void *policyContext,
+ UA_Byte *messageStart, UA_Byte *encryptStart,
+ UA_Byte *sigStart);
+#endif
+
+void
+UA_NetworkMessage_clear(UA_NetworkMessage* p);
void
UA_NetworkMessage_delete(UA_NetworkMessage* p);
@@ -5827,7 +3088,7 @@ UA_StatusCode UA_NetworkMessage_decodeJson(UA_NetworkMessage *dst, const UA_Byte
_UA_END_DECLS
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/src/pubsub/ua_pubsub.h" ***********************************/
+/**** amalgamated original file "/src/pubsub/ua_pubsub.h" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -5835,29 +3096,31 @@ _UA_END_DECLS
*
* Copyright (c) 2017-2018 Fraunhofer IOSB (Author: Andreas Ebner)
* Copyright (c) 2019 Kalycito Infotech Private Limited
+ * Copyright (c) 2020 Yannick Wallerer, Siemens AG
+ * Copyright (c) 2020 Thomas Fischer, Siemens AG
+ * Copyright (c) 2021 Fraunhofer IOSB (Author: Jan Hermes)
*/
+/* The public configuration structs are defined in include/ua_plugin_pubsub.h */
+
_UA_BEGIN_DECLS
-#ifdef UA_ENABLE_PUBSUB /* conditional compilation */
+#ifdef UA_ENABLE_PUBSUB
-/* forward declarations */
struct UA_WriterGroup;
typedef struct UA_WriterGroup UA_WriterGroup;
-/* Declaration for ReaderGroup */
struct UA_ReaderGroup;
typedef struct UA_ReaderGroup UA_ReaderGroup;
-/* The configuration structs (public part of PubSub entities) are defined in include/ua_plugin_pubsub.h */
-
/**********************************************/
/* PublishedDataSet */
/**********************************************/
-typedef struct UA_PublishedDataSet{
+
+typedef struct UA_PublishedDataSet {
UA_PublishedDataSetConfig config;
UA_DataSetMetaDataType dataSetMetaData;
TAILQ_HEAD(UA_ListOfDataSetField, UA_DataSetField) fields;
@@ -5866,57 +3129,78 @@ typedef struct UA_PublishedDataSet{
UA_UInt16 promotedFieldsCount;
UA_UInt16 configurationFreezeCounter;
TAILQ_ENTRY(UA_PublishedDataSet) listEntry;
+ UA_Boolean configurationFrozen;
} UA_PublishedDataSet;
UA_StatusCode
-UA_PublishedDataSetConfig_copy(const UA_PublishedDataSetConfig *src, UA_PublishedDataSetConfig *dst);
+UA_PublishedDataSetConfig_copy(const UA_PublishedDataSetConfig *src,
+ UA_PublishedDataSetConfig *dst);
+
UA_PublishedDataSet *
UA_PublishedDataSet_findPDSbyId(UA_Server *server, UA_NodeId identifier);
+
void
-UA_PublishedDataSet_clear(UA_Server *server, UA_PublishedDataSet *publishedDataSet);
+UA_PublishedDataSet_clear(UA_Server *server,
+ UA_PublishedDataSet *publishedDataSet);
/**********************************************/
/* Connection */
/**********************************************/
-//the connection config (public part of connection) object is defined in include/ua_plugin_pubsub.h
-typedef struct UA_PubSubConnection{
+
+typedef struct UA_PubSubConnection {
+ UA_PubSubComponentEnumType componentType;
UA_PubSubConnectionConfig *config;
- //internal fields
UA_PubSubChannel *channel;
UA_NodeId identifier;
LIST_HEAD(UA_ListOfWriterGroup, UA_WriterGroup) writerGroups;
+ size_t writerGroupsSize;
LIST_HEAD(UA_ListOfPubSubReaderGroup, UA_ReaderGroup) readerGroups;
size_t readerGroupsSize;
TAILQ_ENTRY(UA_PubSubConnection) listEntry;
UA_UInt16 configurationFreezeCounter;
+ UA_Boolean isRegistered; /* Subscriber requires connection channel regist */
+ UA_Boolean configurationFrozen;
} UA_PubSubConnection;
UA_StatusCode
-UA_PubSubConnectionConfig_copy(const UA_PubSubConnectionConfig *src, UA_PubSubConnectionConfig *dst);
+UA_PubSubConnectionConfig_copy(const UA_PubSubConnectionConfig *src,
+ UA_PubSubConnectionConfig *dst);
+
UA_PubSubConnection *
-UA_PubSubConnection_findConnectionbyId(UA_Server *server, UA_NodeId connectionIdentifier);
+UA_PubSubConnection_findConnectionbyId(UA_Server *server,
+ UA_NodeId connectionIdentifier);
+
void
UA_PubSubConnectionConfig_clear(UA_PubSubConnectionConfig *connectionConfig);
+
void
UA_PubSubConnection_clear(UA_Server *server, UA_PubSubConnection *connection);
+
/* Register channel for given connectionIdentifier */
UA_StatusCode
UA_PubSubConnection_regist(UA_Server *server, UA_NodeId *connectionIdentifier);
+/* Process Network Message for a ReaderGroup. But we the ReaderGroup needs to be
+ * identified first. */
+UA_StatusCode
+UA_Server_processNetworkMessage(UA_Server *server,
+ UA_PubSubConnection *connection,
+ UA_NetworkMessage *msg);
+
/**********************************************/
/* DataSetWriter */
/**********************************************/
#ifdef UA_ENABLE_PUBSUB_DELTAFRAMES
-typedef struct UA_DataSetWriterSample{
+typedef struct UA_DataSetWriterSample {
UA_Boolean valueChanged;
UA_DataValue value;
} UA_DataSetWriterSample;
#endif
-typedef struct UA_DataSetWriter{
+typedef struct UA_DataSetWriter {
+ UA_PubSubComponentEnumType componentType;
UA_DataSetWriterConfig config;
- //internal fields
LIST_ENTRY(UA_DataSetWriter) listEntry;
UA_NodeId identifier;
UA_NodeId linkedWriterGroup;
@@ -5924,27 +3208,41 @@ typedef struct UA_DataSetWriter{
UA_ConfigurationVersionDataType connectedDataSetVersion;
UA_PubSubState state;
#ifdef UA_ENABLE_PUBSUB_DELTAFRAMES
- UA_UInt16 deltaFrameCounter; //actual count of sent deltaFrames
+ UA_UInt16 deltaFrameCounter; /* count of sent deltaFrames */
size_t lastSamplesCount;
UA_DataSetWriterSample *lastSamples;
#endif
UA_UInt16 actualDataSetMessageSequenceCount;
+ UA_Boolean configurationFrozen;
} UA_DataSetWriter;
UA_StatusCode
-UA_DataSetWriterConfig_copy(const UA_DataSetWriterConfig *src, UA_DataSetWriterConfig *dst);
+UA_DataSetWriterConfig_copy(const UA_DataSetWriterConfig *src,
+ UA_DataSetWriterConfig *dst);
+
UA_DataSetWriter *
UA_DataSetWriter_findDSWbyId(UA_Server *server, UA_NodeId identifier);
+
UA_StatusCode
-UA_DataSetWriter_setPubSubState(UA_Server *server, UA_PubSubState state, UA_DataSetWriter *dataSetWriter);
+UA_DataSetWriter_setPubSubState(UA_Server *server, UA_PubSubState state,
+ UA_DataSetWriter *dataSetWriter);
+
+UA_StatusCode
+UA_DataSetWriter_generateDataSetMessage(UA_Server *server,
+ UA_DataSetMessage *dataSetMessage,
+ UA_DataSetWriter *dataSetWriter);
+
+UA_StatusCode
+UA_DataSetWriter_remove(UA_Server *server, UA_WriterGroup *linkedWriterGroup,
+ UA_DataSetWriter *dataSetWriter);
/**********************************************/
/* WriterGroup */
/**********************************************/
-struct UA_WriterGroup{
+struct UA_WriterGroup {
+ UA_PubSubComponentEnumType componentType;
UA_WriterGroupConfig config;
- //internal fields
LIST_ENTRY(UA_WriterGroup) listEntry;
UA_NodeId identifier;
UA_PubSubConnection *linkedConnection;
@@ -5955,33 +3253,45 @@ struct UA_WriterGroup{
UA_PubSubState state;
UA_NetworkMessageOffsetBuffer bufferedMessage;
UA_UInt16 sequenceNumber; /* Increased after every succressuly sent message */
+ UA_Boolean configurationFrozen;
+
+#ifdef UA_ENABLE_PUBSUB_ENCRYPTION
+ UA_UInt32 securityTokenId;
+ UA_UInt32 nonceSequenceNumber; /* To be part of the MessageNonce */
+ void *securityPolicyContext;
+#endif
};
UA_StatusCode
-UA_WriterGroupConfig_copy(const UA_WriterGroupConfig *src, UA_WriterGroupConfig *dst);
+UA_WriterGroupConfig_copy(const UA_WriterGroupConfig *src,
+ UA_WriterGroupConfig *dst);
+
UA_WriterGroup *
UA_WriterGroup_findWGbyId(UA_Server *server, UA_NodeId identifier);
+
UA_StatusCode
-UA_WriterGroup_setPubSubState(UA_Server *server, UA_PubSubState state, UA_WriterGroup *writerGroup);
+UA_WriterGroup_setPubSubState(UA_Server *server, UA_PubSubState state,
+ UA_WriterGroup *writerGroup);
/**********************************************/
/* DataSetField */
/**********************************************/
-typedef struct UA_DataSetField{
+typedef struct UA_DataSetField {
UA_DataSetFieldConfig config;
- //internal fields
TAILQ_ENTRY(UA_DataSetField) listEntry;
UA_NodeId identifier;
- UA_NodeId publishedDataSet; //ref to parent pds
- UA_FieldMetaData fieldMetaData;
+ UA_NodeId publishedDataSet; /* parent pds */
+ UA_FieldMetaData fieldMetaData; /* contains the dataSetFieldId */
UA_UInt64 sampleCallbackId;
UA_Boolean sampleCallbackIsRegistered;
-
+ UA_Boolean configurationFrozen;
} UA_DataSetField;
UA_StatusCode
-UA_DataSetFieldConfig_copy(const UA_DataSetFieldConfig *src, UA_DataSetFieldConfig *dst);
+UA_DataSetFieldConfig_copy(const UA_DataSetFieldConfig *src,
+ UA_DataSetFieldConfig *dst);
+
UA_DataSetField *
UA_DataSetField_findDSFbyId(UA_Server *server, UA_NodeId identifier);
@@ -5989,43 +3299,85 @@ UA_DataSetField_findDSFbyId(UA_Server *server, UA_NodeId identifier);
/* DataSetReader */
/**********************************************/
-/* SubscribedDataSetDataType Definition */
-typedef enum {
- UA_PUBSUB_SDS_TARGET,
- UA_PUBSUB_SDS_MIRROR
-}UA_SubscribedDataSetEnumType;
-
/* DataSetReader Type definition */
typedef struct UA_DataSetReader {
+ UA_PubSubComponentEnumType componentType;
UA_DataSetReaderConfig config;
- /* implementation defined fields */
UA_NodeId identifier;
UA_NodeId linkedReaderGroup;
LIST_ENTRY(UA_DataSetReader) listEntry;
- UA_SubscribedDataSetEnumType subscribedDataSetType;
- UA_TargetVariablesDataType subscribedDataSetTarget;
- /* To Do UA_SubscribedDataSetMirrorDataType subscribedDataSetMirror */
-}UA_DataSetReader;
-/* Delete DataSetReader */
-void UA_DataSetReader_delete(UA_Server *server, UA_DataSetReader *dataSetReader);
+ UA_PubSubState state; /* non std */
+ UA_Boolean configurationFrozen;
+ UA_NetworkMessageOffsetBuffer bufferedMessage;
+
+#ifdef UA_ENABLE_PUBSUB_MONITORING
+ /* MessageReceiveTimeout handling */
+ UA_ServerCallback msgRcvTimeoutTimerCallback;
+ UA_UInt64 msgRcvTimeoutTimerId;
+ UA_Boolean msgRcvTimeoutTimerRunning;
+#endif
+} UA_DataSetReader;
/* Process Network Message using DataSetReader */
-void UA_Server_DataSetReader_process(UA_Server *server, UA_DataSetReader *dataSetReader, UA_DataSetMessage* dataSetMsg);
+void
+UA_DataSetReader_process(UA_Server *server,
+ UA_ReaderGroup *readerGroup,
+ UA_DataSetReader *dataSetReader,
+ UA_DataSetMessage *dataSetMsg);
/* Copy the configuration of DataSetReader */
-UA_StatusCode UA_DataSetReaderConfig_copy(const UA_DataSetReaderConfig *src, UA_DataSetReaderConfig *dst);
+UA_StatusCode UA_DataSetReaderConfig_copy(const UA_DataSetReaderConfig *src,
+ UA_DataSetReaderConfig *dst);
+
+/* Clear the configuration of a DataSetReader */
+void UA_DataSetReaderConfig_clear(UA_DataSetReaderConfig *cfg);
+
+/* Copy the configuration of Target Variables */
+UA_StatusCode UA_TargetVariables_copy(const UA_TargetVariables *src,
+ UA_TargetVariables *dst);
+
+/* Clear the Target Variables configuration */
+void UA_TargetVariables_clear(UA_TargetVariables *subscribedDataSetTarget);
+
+/* Copy the configuration of Field Target Variables */
+UA_StatusCode UA_FieldTargetVariable_copy(const UA_FieldTargetVariable *src,
+ UA_FieldTargetVariable *dst);
-/* Add TargetVariables */
UA_StatusCode
-UA_Server_DataSetReader_addTargetVariables(UA_Server* server, UA_NodeId* parentNode, UA_NodeId dataSetReaderIdentifier, UA_SubscribedDataSetEnumType sdsType);
+UA_DataSetReader_setPubSubState(UA_Server *server, UA_PubSubState state,
+ UA_DataSetReader *dataSetReader);
+
+#ifdef UA_ENABLE_PUBSUB_MONITORING
+/* Check if DataSetReader has a message receive timeout */
+void
+UA_DataSetReader_checkMessageReceiveTimeout(UA_Server *server,
+ UA_DataSetReader *dataSetReader);
+
+/* DataSetReader MessageReceiveTimeout callback for generic PubSub component
+ * timeout handling */
+void
+UA_DataSetReader_handleMessageReceiveTimeout(UA_Server *server,
+ void *dataSetReader);
+#endif /* UA_ENABLE_PUBSUB_MONITORING */
+
+UA_StatusCode
+UA_DataSetReader_generateNetworkMessage(UA_PubSubConnection *pubSubConnection,
+ UA_DataSetReader *dataSetReader,
+ UA_DataSetMessage *dsm, UA_UInt16 *writerId,
+ UA_Byte dsmCount, UA_NetworkMessage *nm);
+
+UA_StatusCode
+UA_DataSetReader_generateDataSetMessage(UA_Server *server,
+ UA_DataSetMessage *dataSetMessage,
+ UA_DataSetReader *dataSetReader);
/**********************************************/
/* ReaderGroup */
/**********************************************/
-/* ReaderGroup Type Definition*/
struct UA_ReaderGroup {
+ UA_PubSubComponentEnumType componentType;
UA_ReaderGroupConfig config;
UA_NodeId identifier;
UA_NodeId linkedConnection;
@@ -6034,24 +3386,31 @@ struct UA_ReaderGroup {
/* for simplified information access */
UA_UInt32 readersCount;
UA_UInt64 subscribeCallbackId;
- UA_Boolean subscribeCallbackIsRegistered;
-};
-
-/* Delete ReaderGroup */
-void UA_Server_ReaderGroup_delete(UA_Server *server, UA_ReaderGroup *readerGroup);
+ UA_PubSubState state;
+ UA_Boolean configurationFrozen;
-/* Copy configuration of ReaderGroup */
-UA_StatusCode
-UA_ReaderGroupConfig_copy(const UA_ReaderGroupConfig *src, UA_ReaderGroupConfig *dst);
+#ifdef UA_ENABLE_PUBSUB_ENCRYPTION
+ UA_UInt32 securityTokenId;
+ UA_UInt32 nonceSequenceNumber; /* To be part of the MessageNonce */
+ void *securityPolicyContext;
+#endif
+};
-/* Process Network Message */
UA_StatusCode
-UA_Server_processNetworkMessage(UA_Server *server, UA_NetworkMessage* pMsg, UA_PubSubConnection *pConnection);
+UA_ReaderGroupConfig_copy(const UA_ReaderGroupConfig *src,
+ UA_ReaderGroupConfig *dst);
/* Prototypes for internal util functions - some functions maybe removed later
- *(currently moved from public to internal)*/
-UA_ReaderGroup *UA_ReaderGroup_findRGbyId(UA_Server *server, UA_NodeId identifier);
-UA_DataSetReader *UA_ReaderGroup_findDSRbyId(UA_Server *server, UA_NodeId identifier);
+ * (currently moved from public to internal) */
+UA_ReaderGroup *
+UA_ReaderGroup_findRGbyId(UA_Server *server, UA_NodeId identifier);
+
+UA_DataSetReader *
+UA_ReaderGroup_findDSRbyId(UA_Server *server, UA_NodeId identifier);
+
+UA_StatusCode
+UA_ReaderGroup_setPubSubState(UA_Server *server, UA_PubSubState state,
+ UA_ReaderGroup *readerGroup);
/*********************************************************/
/* PublishValues handling */
@@ -6059,6 +3418,7 @@ UA_DataSetReader *UA_ReaderGroup_findDSRbyId(UA_Server *server, UA_NodeId identi
UA_StatusCode
UA_WriterGroup_addPublishCallback(UA_Server *server, UA_WriterGroup *writerGroup);
+
void
UA_WriterGroup_publishCallback(UA_Server *server, UA_WriterGroup *writerGroup);
@@ -6068,15 +3428,46 @@ UA_WriterGroup_publishCallback(UA_Server *server, UA_WriterGroup *writerGroup);
UA_StatusCode
UA_ReaderGroup_addSubscribeCallback(UA_Server *server, UA_ReaderGroup *readerGroup);
+
+void
+UA_ReaderGroup_removeSubscribeCallback(UA_Server *server, UA_ReaderGroup *readerGroup);
+
void
UA_ReaderGroup_subscribeCallback(UA_Server *server, UA_ReaderGroup *readerGroup);
+/*********************************************************/
+/* Reading Message handling */
+/*********************************************************/
+
+#ifdef UA_ENABLE_PUBSUB_ENCRYPTION
+UA_StatusCode
+verifyAndDecrypt(const UA_Logger *logger, UA_ByteString *buffer,
+ const size_t *currentPosition, const UA_NetworkMessage *nm,
+ UA_Boolean doValidate, UA_Boolean doDecrypt,
+ void *channelContext, UA_PubSubSecurityPolicy *securityPolicy);
+
+UA_StatusCode
+verifyAndDecryptNetworkMessage(const UA_Logger *logger, UA_ByteString *buffer,
+ size_t *currentPosition, UA_NetworkMessage *nm,
+ UA_ReaderGroup *readerGroup);
+#endif
+
+/* Takes a value (and not a pointer) to the buffer. The original buffer is
+ const. Internally we may adjust the length during decryption. */
+UA_StatusCode
+decodeNetworkMessage(UA_Server *server, UA_ByteString *buffer, size_t *pos,
+ UA_NetworkMessage *nm, UA_PubSubConnection *connection);
+
+UA_StatusCode
+receiveBufferedNetworkMessage(UA_Server *server, UA_ReaderGroup *readerGroup,
+ UA_PubSubConnection *connection);
+
#endif /* UA_ENABLE_PUBSUB */
_UA_END_DECLS
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/src/pubsub/ua_pubsub_manager.h" ***********************************/
+/**** amalgamated original file "/src/pubsub/ua_pubsub_manager.h" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -6092,19 +3483,30 @@ _UA_BEGIN_DECLS
#ifdef UA_ENABLE_PUBSUB /* conditional compilation */
-typedef struct UA_PubSubManager{
- //Connections and PublishedDataSets can exist alone (own lifecycle) -> top level components
+typedef struct UA_PubSubManager {
+ /* Connections and PublishedDataSets can exist alone (own lifecycle) -> top
+ * level components */
size_t connectionsSize;
TAILQ_HEAD(UA_ListOfPubSubConnection, UA_PubSubConnection) connections;
+
size_t publishedDataSetsSize;
TAILQ_HEAD(UA_ListOfPublishedDataSet, UA_PublishedDataSet) publishedDataSets;
+
+#ifndef UA_ENABLE_PUBSUB_INFORMATIONMODEL
+ UA_UInt32 uniqueIdCount;
+#endif
} UA_PubSubManager;
void
UA_PubSubManager_delete(UA_Server *server, UA_PubSubManager *pubSubManager);
+#ifndef UA_ENABLE_PUBSUB_INFORMATIONMODEL
void
-UA_PubSubManager_generateUniqueNodeId(UA_Server *server, UA_NodeId *nodeId);
+UA_PubSubManager_generateUniqueNodeId(UA_PubSubManager *psm, UA_NodeId *nodeId);
+#endif
+
+UA_Guid
+UA_PubSubManager_generateUniqueGuid(UA_Server *server);
UA_UInt32
UA_PubSubConfigurationVersionTimeDifference(void);
@@ -6114,19 +3516,32 @@ UA_PubSubConfigurationVersionTimeDifference(void);
/***********************************/
UA_StatusCode
UA_PubSubManager_addRepeatedCallback(UA_Server *server, UA_ServerCallback callback,
- void *data, UA_Double interval_ms, UA_UInt64 *callbackId);
+ void *data, UA_Double interval_ms, UA_DateTime *baseTime,
+ UA_TimerPolicy timerPolicy, UA_UInt64 *callbackId);
UA_StatusCode
-UA_PubSubManager_changeRepeatedCallbackInterval(UA_Server *server, UA_UInt64 callbackId,
- UA_Double interval_ms);
+UA_PubSubManager_changeRepeatedCallback(UA_Server *server, UA_UInt64 callbackId,
+ UA_Double interval_ms, UA_DateTime *baseTime,
+ UA_TimerPolicy timerPolicy);
void
UA_PubSubManager_removeRepeatedPubSubCallback(UA_Server *server, UA_UInt64 callbackId);
+/*************************************************/
+/* PubSub component monitoring */
+/*************************************************/
+
+#ifdef UA_ENABLE_PUBSUB_MONITORING
+
+UA_StatusCode
+UA_PubSubManager_setDefaultMonitoringCallbacks(UA_PubSubMonitoringInterface *monitoringInterface);
+
+#endif /* UA_ENABLE_PUBSUB_MONITORING */
+
#endif /* UA_ENABLE_PUBSUB */
_UA_END_DECLS
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/src/pubsub/ua_pubsub_ns0.h" ***********************************/
+/**** amalgamated original file "/src/pubsub/ua_pubsub_ns0.h" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -6180,13 +3595,16 @@ addDataSetReaderRepresentation(UA_Server *server, UA_DataSetReader *dataSetReade
UA_StatusCode
removeDataSetReaderRepresentation(UA_Server *server, UA_DataSetReader *dataSetReader);
+UA_StatusCode
+removeReaderGroupRepresentation(UA_Server *server, UA_ReaderGroup *readerGroup);
+
#endif /* UA_ENABLE_PUBSUB_INFORMATIONMODEL */
_UA_END_DECLS
#endif /* UA_PUBSUB_NS0_H_ */
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/src/server/ua_server_async.h" ***********************************/
+/**** amalgamated original file "/src/server/ua_server_async.h" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -6247,7 +3665,7 @@ typedef struct {
/* Operations for the workers. The queues are all FIFO: Put in at the tail,
* take out at the head.*/
- UA_LOCK_TYPE(queueLock)
+ UA_Lock queueLock;
UA_AsyncOperationQueue newQueue; /* New operations for the workers */
UA_AsyncOperationQueue dispatchedQueue; /* Operations taken by a worker. When a result is
* returned, we search for the op here to see if it
@@ -6301,7 +3719,7 @@ UA_FUNC_ATTR_WARN_UNUSED_RESULT;
_UA_END_DECLS
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/src/server/ua_server_internal.h" ***********************************/
+/**** amalgamated original file "/src/server/ua_server_internal.h" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -6358,13 +3776,13 @@ typedef enum {
} UA_DiagnosticEvent;
typedef struct channel_entry {
- UA_DelayedCallback cleanupCallback;
+ UA_TimerEntry cleanupCallback;
TAILQ_ENTRY(channel_entry) pointers;
UA_SecureChannel channel;
} channel_entry;
typedef struct session_list_entry {
- UA_DelayedCallback cleanupCallback;
+ UA_TimerEntry cleanupCallback;
LIST_ENTRY(session_list_entry) pointers;
UA_Session session;
} session_list_entry;
@@ -6395,6 +3813,7 @@ struct UA_Server {
/* Session Management */
LIST_HEAD(session_list, session_list_entry) sessions;
UA_UInt32 sessionCount;
+ UA_UInt32 activeSessionCount;
UA_Session adminSession; /* Local access to the services (for startup and
* maintenance) uses this Session with all possible
* access rights (Session Id: 1) */
@@ -6406,9 +3825,6 @@ struct UA_Server {
/* Callbacks with a repetition interval */
UA_Timer timer;
- /* WorkQueue and worker threads */
- UA_WorkQueue workQueue;
-
/* For bootstrapping, omit some consistency checks, creating a reference to
* the parent and member instantiation */
UA_Boolean bootstrapNS0;
@@ -6418,19 +3834,22 @@ struct UA_Server {
UA_DiscoveryManager discoveryManager;
#endif
- /* DataChange Subscriptions */
+ /* Subscriptions */
#ifdef UA_ENABLE_SUBSCRIPTIONS
- /* Num active subscriptions */
- UA_UInt32 numSubscriptions;
- /* Num active monitored items */
- UA_UInt32 numMonitoredItems;
+ size_t subscriptionsSize; /* Number of active subscriptions */
+ size_t monitoredItemsSize; /* Number of active monitored items */
+ LIST_HEAD(, UA_Subscription) subscriptions; /* All subscriptions in the
+ * server. They may be detached
+ * from a session. */
+ UA_UInt32 lastSubscriptionId; /* To generate unique SubscriptionIds */
+
/* To be cast to UA_LocalMonitoredItem to get the callback and context */
- LIST_HEAD(LocalMonitoredItems, UA_MonitoredItem) localMonitoredItems;
+ LIST_HEAD(, UA_MonitoredItem) localMonitoredItems;
UA_UInt32 lastLocalMonitoredItemId;
-#ifdef UA_ENABLE_SUBSCRIPTIONS_ALARMS_CONDITIONS
- LIST_HEAD(conditionSourcelisthead, UA_ConditionSource) headConditionSource;
-#endif//UA_ENABLE_SUBSCRIPTIONS_ALARMS_CONDITIONS
+# ifdef UA_ENABLE_SUBSCRIPTIONS_ALARMS_CONDITIONS
+ LIST_HEAD(, UA_ConditionSource) conditionSources;
+# endif
#endif
@@ -6440,19 +3859,31 @@ struct UA_Server {
#endif
#if UA_MULTITHREADING >= 100
- UA_LOCK_TYPE(networkMutex)
- UA_LOCK_TYPE(serviceMutex)
+ UA_Lock networkMutex;
+ UA_Lock serviceMutex;
#endif
/* Statistics */
- UA_ServerStatistics serverStats;
+ UA_NetworkStatistics networkStatistics;
+ UA_SecureChannelStatistics secureChannelStatistics;
+ UA_ServerDiagnosticsSummaryDataType serverDiagnosticsSummary;
};
+/***********************/
+/* References Handling */
+/***********************/
+
+extern const struct aa_head refNameTree;
+
+const UA_ReferenceTarget *
+UA_NodeReferenceKind_findTarget(const UA_NodeReferenceKind *rk,
+ const UA_ExpandedNodeId *targetId);
+
/**************************/
/* SecureChannel Handling */
/**************************/
-/* Remove a all securechannels */
+/* Remove all securechannels */
void
UA_Server_deleteSecureChannels(UA_Server *server);
@@ -6465,17 +3896,24 @@ UA_StatusCode
UA_Server_createSecureChannel(UA_Server *server, UA_Connection *connection);
UA_StatusCode
-UA_Server_configSecureChannel(UA_Server *server, UA_SecureChannel *channel,
+UA_Server_configSecureChannel(void *application, UA_SecureChannel *channel,
const UA_AsymmetricAlgorithmSecurityHeader *asymHeader);
UA_StatusCode
-sendServiceFault(UA_SecureChannel *channel, UA_UInt32 requestId, UA_UInt32 requestHandle,
- const UA_DataType *responseType, UA_StatusCode statusCode);
+sendServiceFault(UA_SecureChannel *channel, UA_UInt32 requestId,
+ UA_UInt32 requestHandle, UA_StatusCode statusCode);
void
UA_Server_closeSecureChannel(UA_Server *server, UA_SecureChannel *channel,
UA_DiagnosticEvent event);
+/* Gets the a pointer to the context of a security policy supported by the
+ * server matched by the security policy uri. */
+UA_SecurityPolicy *
+getSecurityPolicyByUri(const UA_Server *server,
+ const UA_ByteString *securityPolicyUri);
+
+
/********************/
/* Session Handling */
/********************/
@@ -6485,6 +3923,10 @@ getNamespaceByName(UA_Server *server, const UA_String namespaceUri,
size_t *foundIndex);
UA_StatusCode
+getNamespaceByIndex(UA_Server *server, const size_t namespaceIndex,
+ UA_String *foundUri);
+
+UA_StatusCode
getBoundSession(UA_Server *server, const UA_SecureChannel *channel,
const UA_NodeId *token, UA_Session **session);
@@ -6513,12 +3955,6 @@ UA_Server_getSessionById(UA_Server *server, const UA_NodeId *sessionId);
/* Node Handling */
/*****************/
-/* Deletes references from the node which are not matching any type in the given
- * array. Could be used to e.g. delete all the references, except
- * 'HASMODELINGRULE' */
-void UA_Node_deleteReferencesSubset(UA_Node *node, size_t referencesSkipSize,
- UA_NodeId* referencesSkip);
-
/* Calls the callback with the node retrieved from the nodestore on top of the
* stack. Either a copy or the original node for in-situ editing. Depends on
* multithreading and the nodestore.*/
@@ -6533,49 +3969,54 @@ UA_StatusCode UA_Server_editNode(UA_Server *server, UA_Session *session,
/* Utility Functions */
/*********************/
-/* A few global NodeId definitions */
-extern const UA_NodeId subtypeId;
-extern const UA_NodeId hierarchicalReferences;
-
void setupNs1Uri(UA_Server *server);
UA_UInt16 addNamespace(UA_Server *server, const UA_String name);
UA_Boolean
-UA_Node_hasSubTypeOrInstances(const UA_Node *node);
+UA_Node_hasSubTypeOrInstances(const UA_NodeHead *head);
/* Recursively searches "upwards" in the tree following specific reference types */
UA_Boolean
isNodeInTree(UA_Server *server, const UA_NodeId *leafNode,
- const UA_NodeId *nodeToFind, const UA_NodeId *referenceTypeIds,
- size_t referenceTypeIdsSize);
+ const UA_NodeId *nodeToFind, const UA_ReferenceTypeSet *relevantRefs);
+
+/* Convenience function with just a single ReferenceTypeIndex */
+UA_Boolean
+isNodeInTree_singleRef(UA_Server *server, const UA_NodeId *leafNode,
+ const UA_NodeId *nodeToFind, const UA_Byte relevantRefTypeIndex);
/* Returns an array with the hierarchy of nodes. The start nodes can be returned
* as well. The returned array starts at the leaf and continues "upwards" or
- * "downwards". Duplicate entries are removed. The parameter `walkDownwards`
- * indicates the direction of search. */
+ * "downwards". Duplicate entries are removed. */
UA_StatusCode
-browseRecursive(UA_Server *server,
- size_t startNodesSize, const UA_NodeId *startNodes,
- size_t refTypesSize, const UA_NodeId *refTypes,
- UA_BrowseDirection browseDirection, UA_Boolean includeStartNodes,
+browseRecursive(UA_Server *server, size_t startNodesSize, const UA_NodeId *startNodes,
+ UA_BrowseDirection browseDirection, const UA_ReferenceTypeSet *refTypes,
+ UA_UInt32 nodeClassMask, UA_Boolean includeStartNodes,
size_t *resultsSize, UA_ExpandedNodeId **results);
-/* If refTypes is non-NULL, tries to realloc and increase the length */
+/* Get the bitfield indices of a ReferenceType and possibly its subtypes.
+ * refType must point to a ReferenceTypeNode. */
UA_StatusCode
-referenceSubtypes(UA_Server *server, const UA_NodeId *refType,
- size_t *refTypesSize, UA_NodeId **refTypes);
+referenceTypeIndices(UA_Server *server, const UA_NodeId *refType,
+ UA_ReferenceTypeSet *indices, UA_Boolean includeSubtypes);
/* Returns the recursive type and interface hierarchy of the node */
UA_StatusCode
getParentTypeAndInterfaceHierarchy(UA_Server *server, const UA_NodeId *typeNode,
UA_NodeId **typeHierarchy, size_t *typeHierarchySize);
+/* Returns the recursive interface hierarchy of the node */
+UA_StatusCode
+getAllInterfaceChildNodeIds(UA_Server *server, const UA_NodeId *objectNode, const UA_NodeId *objectTypeNode,
+ UA_NodeId **interfaceChildNodes, size_t *interfaceChildNodesSize);
+
#ifdef UA_ENABLE_SUBSCRIPTIONS_ALARMS_CONDITIONS
-UA_StatusCode UA_EXPORT
-UA_getConditionId(UA_Server *server, const UA_NodeId *conditionNodeId, UA_NodeId *outConditionId);
+UA_StatusCode
+UA_getConditionId(UA_Server *server, const UA_NodeId *conditionNodeId,
+ UA_NodeId *outConditionId);
-void UA_EXPORT
+void
UA_ConditionList_delete(UA_Server *server);
UA_Boolean
@@ -6584,15 +4025,12 @@ isConditionOrBranch(UA_Server *server,
const UA_NodeId *conditionSource,
UA_Boolean *isCallerAC);
-#endif//UA_ENABLE_SUBSCRIPTIONS_ALARMS_CONDITIONS
+#endif /* UA_ENABLE_SUBSCRIPTIONS_ALARMS_CONDITIONS */
+
/* Returns the type node from the node on the stack top. The type node is pushed
* on the stack and returned. */
-const UA_Node * getNodeType(UA_Server *server, const UA_Node *node);
-
-/* Write a node attribute with a defined session */
-UA_StatusCode
-writeWithSession(UA_Server *server, UA_Session *session,
- const UA_WriteValue *value);
+const UA_Node *
+getNodeType(UA_Server *server, const UA_NodeHead *nodeHead);
UA_StatusCode
sendResponse(UA_Server *server, UA_Session *session, UA_SecureChannel *channel,
@@ -6630,22 +4068,25 @@ addNode(UA_Server *server, const UA_NodeClass nodeClass, const UA_NodeId *reques
void *nodeContext, UA_NodeId *outNewNodeId);
UA_StatusCode
-setVariableNode_dataSource(UA_Server *server, const UA_NodeId nodeId,
- const UA_DataSource dataSource);
+addRef(UA_Server *server, UA_Session *session, const UA_NodeId *sourceId,
+ const UA_NodeId *referenceTypeId, const UA_NodeId *targetId,
+ UA_Boolean forward);
UA_StatusCode
-setMethodNode_callback(UA_Server *server,
- const UA_NodeId methodNodeId,
- UA_MethodCallback methodCallback);
+setVariableNode_dataSource(UA_Server *server, const UA_NodeId nodeId,
+ const UA_DataSource dataSource);
UA_StatusCode
-writeAttribute(UA_Server *server, const UA_WriteValue *value);
+writeAttribute(UA_Server *server, UA_Session *session,
+ const UA_NodeId *nodeId, const UA_AttributeId attributeId,
+ const void *attr, const UA_DataType *attr_type);
-UA_StatusCode
-writeWithWriteValue(UA_Server *server, const UA_NodeId *nodeId,
- const UA_AttributeId attributeId,
- const UA_DataType *attr_type,
- const void *attr);
+static UA_INLINE UA_StatusCode
+writeValueAttribute(UA_Server *server, UA_Session *session,
+ const UA_NodeId *nodeId, const UA_Variant *value) {
+ return writeAttribute(server, session, nodeId, UA_ATTRIBUTEID_VALUE,
+ value, &UA_TYPES[UA_TYPES_VARIANT]);
+}
UA_DataValue
readAttribute(UA_Server *server, const UA_ReadValueId *item,
@@ -6664,9 +4105,27 @@ UA_BrowsePathResult
translateBrowsePathToNodeIds(UA_Server *server, const UA_BrowsePath *browsePath);
#ifdef UA_ENABLE_SUBSCRIPTIONS
-void
-monitoredItem_sampleCallback(UA_Server *server, UA_MonitoredItem *monitoredItem);
-#endif
+
+void monitoredItem_sampleCallback(UA_Server *server, UA_MonitoredItem *monitoredItem);
+
+UA_Subscription *
+UA_Server_getSubscriptionById(UA_Server *server, UA_UInt32 subscriptionId);
+
+#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
+UA_StatusCode
+triggerEvent(UA_Server *server, const UA_NodeId eventNodeId,
+ const UA_NodeId origin, UA_ByteString *outEventId,
+ const UA_Boolean deleteEventNode);
+
+/* Filters the given event with the given filter and writes the results into a
+ * notification */
+UA_StatusCode
+filterEvent(UA_Server *server, UA_Session *session,
+ const UA_NodeId *eventNode, UA_EventFilter *filter,
+ UA_EventFieldList *efl, UA_EventFilterResult *result);
+
+#endif /* UA_ENABLE_SUBSCRIPTIONS_EVENTS */
+#endif /* UA_ENABLE_SUBSCRIPTIONS */
UA_BrowsePathResult
browseSimplifiedBrowsePath(UA_Server *server, const UA_NodeId origin,
@@ -6679,6 +4138,9 @@ writeObjectProperty(UA_Server *server, const UA_NodeId objectId,
UA_StatusCode
getNodeContext(UA_Server *server, UA_NodeId nodeId, void **nodeContext);
+UA_StatusCode
+setNodeContext(UA_Server *server, UA_NodeId nodeId, void *nodeContext);
+
void
removeCallback(UA_Server *server, UA_UInt64 callbackId);
@@ -6696,6 +4158,55 @@ register_server_with_discovery_server(UA_Server *server,
const UA_Boolean isUnregister,
const char* semaphoreFilePath);
#endif
+
+/***********/
+/* RefTree */
+/***********/
+
+/* A RefTree is a sorted set of NodeIds that ensures we consider each node just
+ * once. It holds a single array for both the ExpandedNodeIds and the entries of
+ * a tree-structure for fast lookup. A single realloc operation (with some
+ * pointer repairing) can be used to increase the capacity of the RefTree.
+ *
+ * When the RefTree is complete, the tree-part at the end of the targets array
+ * can be ignored / cut away to use it as a simple ExpandedNodeId array.
+ *
+ * The layout of the targets array is as follows:
+ *
+ * | Targets [ExpandedNodeId, n times] | Tree [RefEntry, n times] | */
+
+#define UA_REFTREE_INITIAL_SIZE 16
+
+typedef struct RefEntry {
+ ZIP_ENTRY(RefEntry) zipfields;
+ const UA_ExpandedNodeId *target;
+ UA_UInt32 targetHash; /* Hash of the target nodeid */
+} RefEntry;
+
+ZIP_HEAD(RefHead, RefEntry);
+typedef struct RefHead RefHead;
+
+typedef struct {
+ UA_ExpandedNodeId *targets;
+ RefHead head;
+ size_t capacity; /* available space */
+ size_t size; /* used space */
+} RefTree;
+
+UA_StatusCode UA_FUNC_ATTR_WARN_UNUSED_RESULT
+RefTree_init(RefTree *rt);
+
+void RefTree_clear(RefTree *rt);
+
+UA_StatusCode UA_FUNC_ATTR_WARN_UNUSED_RESULT
+RefTree_addNodeId(RefTree *rt, const UA_NodeId *target, UA_Boolean *duplicate);
+
+UA_Boolean
+RefTree_contains(RefTree *rt, const UA_ExpandedNodeId *target);
+
+UA_Boolean
+RefTree_containsNodeId(RefTree *rt, const UA_NodeId *target);
+
/***************************************/
/* Check Information Model Consistency */
/***************************************/
@@ -6718,12 +4229,31 @@ readValueAttribute(UA_Server *server, UA_Session *session,
* - array dimensions.
* Sometimes it can be necessary to transform the content of the value, e.g.
* byte array to bytestring or uint32 to some enum. If editableValue is non-NULL,
- * we try to create a matching variant that points to the original data. */
+ * we try to create a matching variant that points to the original data.
+ *
+ * The reason is set whenever the return value is false */
UA_Boolean
compatibleValue(UA_Server *server, UA_Session *session, const UA_NodeId *targetDataTypeId,
UA_Int32 targetValueRank, size_t targetArrayDimensionsSize,
const UA_UInt32 *targetArrayDimensions, const UA_Variant *value,
- const UA_NumericRange *range);
+ const UA_NumericRange *range, const char **reason);
+
+/* Is the DataType compatible */
+UA_Boolean
+compatibleDataTypes(UA_Server *server, const UA_NodeId *dataType,
+ const UA_NodeId *constraintDataType);
+
+/* Set to the target type if compatible */
+void
+adjustValueType(UA_Server *server, UA_Variant *value,
+ const UA_NodeId *targetDataTypeId);
+
+/* Is the Value compatible with the DataType? Can perform additional checks
+ * compared to compatibleDataTypes. */
+UA_Boolean
+compatibleValueDataType(UA_Server *server, const UA_DataType *dataType,
+ const UA_NodeId *constraintDataType);
+
UA_Boolean
compatibleArrayDimensions(size_t constraintArrayDimensionsSize,
@@ -6740,10 +4270,6 @@ compatibleValueRankArrayDimensions(UA_Server *server, UA_Session *session,
UA_Int32 valueRank, size_t arrayDimensionsSize);
UA_Boolean
-compatibleDataType(UA_Server *server, const UA_NodeId *dataType,
- const UA_NodeId *constraintDataType, UA_Boolean isValue);
-
-UA_Boolean
compatibleValueRanks(UA_Int32 valueRank, UA_Int32 constraintValueRank);
struct BrowseOpts {
@@ -6788,6 +4314,39 @@ UA_StatusCode UA_Server_initNS0(UA_Server *server);
UA_StatusCode writeNs0VariableArray(UA_Server *server, UA_UInt32 id, void *v,
size_t length, const UA_DataType *type);
+#ifdef UA_ENABLE_DIAGNOSTICS
+void createSessionObject(UA_Server *server, UA_Session *session);
+
+void createSubscriptionObject(UA_Server *server, UA_Session *session,
+ UA_Subscription *sub);
+
+UA_StatusCode
+readDiagnostics(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext,
+ const UA_NodeId *nodeId, void *nodeContext, UA_Boolean sourceTimestamp,
+ const UA_NumericRange *range, UA_DataValue *value);
+
+UA_StatusCode
+readSubscriptionDiagnosticsArray(UA_Server *server,
+ const UA_NodeId *sessionId, void *sessionContext,
+ const UA_NodeId *nodeId, void *nodeContext,
+ UA_Boolean sourceTimestamp,
+ const UA_NumericRange *range, UA_DataValue *value);
+
+UA_StatusCode
+readSessionDiagnosticsArray(UA_Server *server,
+ const UA_NodeId *sessionId, void *sessionContext,
+ const UA_NodeId *nodeId, void *nodeContext,
+ UA_Boolean sourceTimestamp,
+ const UA_NumericRange *range, UA_DataValue *value);
+
+UA_StatusCode
+readSessionSecurityDiagnostics(UA_Server *server,
+ const UA_NodeId *sessionId, void *sessionContext,
+ const UA_NodeId *nodeId, void *nodeContext,
+ UA_Boolean sourceTimestamp,
+ const UA_NumericRange *range, UA_DataValue *value);
+#endif
+
/***************************/
/* Nodestore Access Macros */
/***************************/
@@ -6801,6 +4360,10 @@ UA_StatusCode writeNs0VariableArray(UA_Server *server, UA_UInt32 id, void *v,
#define UA_NODESTORE_GET(server, nodeid) \
server->config.nodestore.getNode(server->config.nodestore.context, nodeid)
+/* Returns NULL if the target is an external Reference (per the ExpandedNodeId) */
+const UA_Node *
+UA_NODESTORE_GETFROMREF(UA_Server *server, UA_NodePointer target);
+
#define UA_NODESTORE_RELEASE(server, node) \
server->config.nodestore.releaseNode(server->config.nodestore.context, node)
@@ -6818,10 +4381,14 @@ UA_StatusCode writeNs0VariableArray(UA_Server *server, UA_UInt32 id, void *v,
#define UA_NODESTORE_REMOVE(server, nodeId) \
server->config.nodestore.removeNode(server->config.nodestore.context, nodeId)
+#define UA_NODESTORE_GETREFERENCETYPEID(server, index) \
+ server->config.nodestore.getReferenceTypeId(server->config.nodestore.context, \
+ index)
+
_UA_END_DECLS
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/src/server/ua_services.h" ***********************************/
+/**** amalgamated original file "/src/server/ua_services.h" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -7005,7 +4572,11 @@ void Service_CloseSession(UA_Server *server, UA_SecureChannel *channel,
*
* AddNodes Service
* ^^^^^^^^^^^^^^^^
- * Used to add one or more Nodes into the AddressSpace hierarchy. */
+ * Used to add one or more Nodes into the AddressSpace hierarchy.
+ * If the type or one of the supertypes has any HasInterface references
+ * (see OPC 10001-7 - Amendment 7, 4.9.2), the child nodes of the interfaces
+ * are added to the new object.
+*/
void Service_AddNodes(UA_Server *server, UA_Session *session,
const UA_AddNodesRequest *request,
UA_AddNodesResponse *response);
@@ -7013,7 +4584,7 @@ void Service_AddNodes(UA_Server *server, UA_Session *session,
/**
* AddReferences Service
* ^^^^^^^^^^^^^^^^^^^^^
- * Used to add one or more References to one or more Nodes. */
+ * Used to add one or more References to one or more Nodes.*/
void Service_AddReferences(UA_Server *server, UA_Session *session,
const UA_AddReferencesRequest *request,
UA_AddReferencesResponse *response);
@@ -7245,7 +4816,9 @@ void Service_SetMonitoringMode(UA_Server *server, UA_Session *session,
* SetTriggering Service
* ^^^^^^^^^^^^^^^^^^^^^
* Used to create and delete triggering links for a triggering item. */
-/* Not Implemented */
+void Service_SetTriggering(UA_Server *server, UA_Session *session,
+ const UA_SetTriggeringRequest *request,
+ UA_SetTriggeringResponse *response);
/**
* Subscription Service Set
@@ -7287,9 +4860,13 @@ void Service_SetPublishingMode(UA_Server *server, UA_Session *session,
*
* Note that the service signature is an exception and does not contain a
* pointer to a PublishResponse. That is because the service queues up publish
- * requests internally and sends responses asynchronously based on timeouts. */
-void Service_Publish(UA_Server *server, UA_Session *session,
- const UA_PublishRequest *request, UA_UInt32 requestId);
+ * requests internally and sends responses asynchronously based on timeouts.
+ *
+ * Also, this is the only service method that returns a StatusCode. This
+ * simplifies keeping track of the diagnostics statistics. */
+UA_StatusCode
+Service_Publish(UA_Server *server, UA_Session *session,
+ const UA_PublishRequest *request, UA_UInt32 requestId);
/**
* Republish Service
@@ -7317,14 +4894,16 @@ void Service_DeleteSubscriptions(UA_Server *server, UA_Session *session,
* its Subscriptions to that Session. It may also be used by one Client to take
* over a Subscription from another Client by transferring the Subscription to
* its Session. */
-/* Not Implemented */
+void Service_TransferSubscriptions(UA_Server *server, UA_Session *session,
+ const UA_TransferSubscriptionsRequest *request,
+ UA_TransferSubscriptionsResponse *response);
#endif /* UA_ENABLE_SUBSCRIPTIONS */
_UA_END_DECLS
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/src/client/ua_client_internal.h" ***********************************/
+/**** amalgamated original file "/src/client/ua_client_internal.h" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -7419,13 +4998,11 @@ void
UA_Client_AsyncService_removeAll(UA_Client *client, UA_StatusCode statusCode);
typedef struct CustomCallback {
- LIST_ENTRY(CustomCallback) pointers;
UA_UInt32 callbackId;
UA_ClientAsyncServiceCallback userCallback;
void *userData;
- bool isAsync;
void *clientData;
} CustomCallback;
@@ -7466,7 +5043,6 @@ struct UA_Client {
/* Async Service */
LIST_HEAD(, AsyncServiceCall) asyncServiceCalls;
- LIST_HEAD(, CustomCallback) customCallbacks;
/* Subscriptions */
#ifdef UA_ENABLE_SUBSCRIPTIONS
@@ -7480,9 +5056,8 @@ struct UA_Client {
void notifyClientState(UA_Client *client);
void processERRResponse(UA_Client *client, const UA_ByteString *chunk);
void processACKResponse(UA_Client *client, const UA_ByteString *chunk);
-void processOPNResponse(UA_Client *client, UA_ByteString *chunk);
+void processOPNResponse(UA_Client *client, const UA_ByteString *message);
void closeSecureChannel(UA_Client *client);
-void renewSecureChannel(UA_Client *client);
UA_StatusCode
connectIterate(UA_Client *client, UA_UInt32 timeout);
@@ -7493,7 +5068,36 @@ receiveResponseAsync(UA_Client *client, UA_UInt32 timeout);
_UA_END_DECLS
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/build/src_generated/open62541/namespace0_generated.h" ***********************************/
+/**** amalgamated original file "/src/pubsub/ua_pubsub_config.h" ****/
+
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Copyright (c) 2020 Yannick Wallerer, Siemens AG
+ * Copyright (c) 2020 Thomas Fischer, Siemens AG
+ */
+
+#ifdef UA_ENABLE_PUBSUB_FILE_CONFIG
+
+
+
+/* Decodes the information from the ByteString. If the decoded content is a
+ * PubSubConfiguration in a UABinaryFileDataType-object. It will overwrite the
+ * current PubSub configuration from the server. */
+UA_StatusCode
+UA_PubSubManager_loadPubSubConfigFromByteString(UA_Server *server,
+ const UA_ByteString buffer);
+
+/* Saves the current PubSub configuration of a server in a byteString. */
+UA_StatusCode
+UA_PubSubManager_getEncodedPubSubConfiguration(UA_Server *server,
+ UA_ByteString *buffer);
+
+
+#endif /* UA_ENABLE_PUBSUB_FILE_CONFIG */
+
+/**** amalgamated original file "/build/src_generated/open62541/namespace0_generated.h" ****/
/* WARNING: This is a generated file.
* Any manual changes will be overwritten. */
@@ -7544,7 +5148,7 @@ _UA_END_DECLS
#endif /* NAMESPACE0_GENERATED_H_ */
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/src/ua_types.c" ***********************************/
+/**** amalgamated original file "/src/ua_types.c" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -7576,49 +5180,53 @@ _UA_END_DECLS
/* Global definition of NULL type instances. These are always zeroed out, as
* mandated by the C/C++ standard for global values with no initializer. */
-const UA_String UA_STRING_NULL = {0, NULL};
-const UA_ByteString UA_BYTESTRING_NULL = {0, NULL};
-const UA_Guid UA_GUID_NULL = {0, 0, 0, {0,0,0,0,0,0,0,0}};
-const UA_NodeId UA_NODEID_NULL = {0, UA_NODEIDTYPE_NUMERIC, {0}};
-const UA_ExpandedNodeId UA_EXPANDEDNODEID_NULL = {{0, UA_NODEIDTYPE_NUMERIC, {0}}, {0, NULL}, 0};
-
-typedef UA_StatusCode (*UA_copySignature)(const void *src, void *dst,
- const UA_DataType *type);
-typedef void (*UA_clearSignature)(void *p, const UA_DataType *type);
-
+const UA_String UA_STRING_NULL = {0};
+const UA_ByteString UA_BYTESTRING_NULL = {0};
+const UA_Guid UA_GUID_NULL = {0};
+const UA_NodeId UA_NODEID_NULL = {0};
+const UA_ExpandedNodeId UA_EXPANDEDNODEID_NULL = {0};
+
+typedef UA_StatusCode
+(*UA_copySignature)(const void *src, void *dst, const UA_DataType *type);
extern const UA_copySignature copyJumpTable[UA_DATATYPEKINDS];
+
+typedef void (*UA_clearSignature)(void *p, const UA_DataType *type);
extern const UA_clearSignature clearJumpTable[UA_DATATYPEKINDS];
-/* TODO: The standard-defined types are ordered. See if binary search is
- * more efficient. */
-const UA_DataType *
-UA_findDataType(const UA_NodeId *typeId) {
- if(typeId->identifierType != UA_NODEIDTYPE_NUMERIC)
- return NULL;
+typedef UA_Order
+(*UA_orderSignature)(const void *p1, const void *p2, const UA_DataType *type);
+extern const UA_orderSignature orderJumpTable[UA_DATATYPEKINDS];
- /* Always look in built-in types first
- * (may contain data types from all namespaces) */
+const UA_DataType *
+UA_findDataTypeWithCustom(const UA_NodeId *typeId,
+ const UA_DataTypeArray *customTypes) {
+ /* Always look in built-in types first (may contain data types from all
+ * namespaces).
+ *
+ * TODO: The standard-defined types are ordered. See if binary search is
+ * more efficient. */
for(size_t i = 0; i < UA_TYPES_COUNT; ++i) {
- if(UA_TYPES[i].typeId.identifier.numeric == typeId->identifier.numeric
- && UA_TYPES[i].typeId.namespaceIndex == typeId->namespaceIndex)
+ if(UA_NodeId_equal(&UA_TYPES[i].typeId, typeId))
return &UA_TYPES[i];
}
- /* TODO When other namespace look in custom types, too, requires access to custom types array here! */
- /*if(typeId->namespaceIndex != 0) {
- size_t customTypesArraySize;
- const UA_DataType *customTypesArray;
- UA_getCustomTypes(&customTypesArraySize, &customTypesArray);
- for(size_t i = 0; i < customTypesArraySize; ++i) {
- if(customTypesArray[i].typeId.identifier.numeric == typeId->identifier.numeric
- && customTypesArray[i].typeId.namespaceIndex == typeId->namespaceIndex)
- return &customTypesArray[i];
+ /* Search in the customTypes */
+ while(customTypes) {
+ for(size_t i = 0; i < customTypes->typesSize; ++i) {
+ if(UA_NodeId_equal(&customTypes->types[i].typeId, typeId))
+ return &customTypes->types[i];
}
- }*/
+ customTypes = customTypes->next;
+ }
return NULL;
}
+const UA_DataType *
+UA_findDataType(const UA_NodeId *typeId) {
+ return UA_findDataTypeWithCustom(typeId, NULL);
+}
+
/***************************/
/* Random Number Generator */
/***************************/
@@ -7648,7 +5256,7 @@ UA_String_fromChars(const char *src) {
s.length = strlen(src);
if(s.length > 0) {
s.data = (u8*)UA_malloc(s.length);
- if(!s.data) {
+ if(UA_UNLIKELY(!s.data)) {
s.length = 0;
return s;
}
@@ -7659,26 +5267,42 @@ UA_String_fromChars(const char *src) {
return s;
}
+static UA_Order
+stringOrder(const UA_String *p1, const UA_String *p2, const UA_DataType *type);
+static UA_Order
+guidOrder(const UA_Guid *p1, const UA_Guid *p2, const UA_DataType *type);
+static UA_Order
+qualifiedNameOrder(const UA_QualifiedName *p1, const UA_QualifiedName *p2,
+ const UA_DataType *type);
+
UA_Boolean
UA_String_equal(const UA_String *s1, const UA_String *s2) {
+ return (stringOrder(s1, s2, NULL) == UA_ORDER_EQ);
+}
+
+/* Do not expose UA_String_equal_ignorecase to public API as it currently only handles
+ * ASCII strings, and not UTF8! */
+UA_Boolean
+UA_String_equal_ignorecase(const UA_String *s1, const UA_String *s2) {
if(s1->length != s2->length)
return false;
if(s1->length == 0)
return true;
if(s2->data == NULL)
return false;
- i32 is = memcmp((char const*)s1->data,
- (char const*)s2->data, s1->length);
- return (is == 0) ? true : false;
+
+ //FIXME this currently does not handle UTF8
+ return UA_strncasecmp((const char*)s1->data, (const char*)s2->data, s1->length) == 0;
}
static UA_StatusCode
String_copy(UA_String const *src, UA_String *dst, const UA_DataType *_) {
- UA_StatusCode retval = UA_Array_copy(src->data, src->length, (void**)&dst->data,
- &UA_TYPES[UA_TYPES_BYTE]);
- if(retval == UA_STATUSCODE_GOOD)
+ UA_StatusCode res =
+ UA_Array_copy(src->data, src->length, (void**)&dst->data,
+ &UA_TYPES[UA_TYPES_BYTE]);
+ if(res == UA_STATUSCODE_GOOD)
dst->length = src->length;
- return retval;
+ return res;
}
static void
@@ -7688,7 +5312,8 @@ String_clear(UA_String *s, const UA_DataType *_) {
/* QualifiedName */
static UA_StatusCode
-QualifiedName_copy(const UA_QualifiedName *src, UA_QualifiedName *dst, const UA_DataType *_) {
+QualifiedName_copy(const UA_QualifiedName *src, UA_QualifiedName *dst,
+ const UA_DataType *_) {
dst->namespaceIndex = src->namespaceIndex;
return String_copy(&src->name, &dst->name, NULL);
}
@@ -7707,43 +5332,39 @@ UA_QualifiedName_hash(const UA_QualifiedName *q) {
UA_Boolean
UA_QualifiedName_equal(const UA_QualifiedName *qn1,
const UA_QualifiedName *qn2) {
- if(qn1 == NULL || qn2 == NULL)
- return false;
- if(qn1->namespaceIndex != qn2->namespaceIndex)
- return false;
- if(qn1->name.length != qn2->name.length)
- return false;
- return (memcmp((char const*)qn1->name.data,
- (char const*)qn2->name.data, qn1->name.length) == 0);
+ return (qualifiedNameOrder(qn1, qn2, NULL) == UA_ORDER_EQ);
}
/* DateTime */
UA_DateTimeStruct
UA_DateTime_toStruct(UA_DateTime t) {
- /* Calculating the the milli-, micro- and nanoseconds */
- UA_DateTimeStruct dateTimeStruct;
- if(t >= 0) {
- dateTimeStruct.nanoSec = (u16)((t % 10) * 100);
- dateTimeStruct.microSec = (u16)((t % 10000) / 10);
- dateTimeStruct.milliSec = (u16)((t % 10000000) / 10000);
- } else {
- dateTimeStruct.nanoSec = (u16)(((t % 10 + t) % 10) * 100);
- dateTimeStruct.microSec = (u16)(((t % 10000 + t) % 10000) / 10);
- dateTimeStruct.milliSec = (u16)(((t % 10000000 + t) % 10000000) / 10000);
- }
-
- /* Calculating the unix time with #include <time.h> */
+ /* Divide, then subtract -> avoid underflow. Also, negative numbers are
+ * rounded up, not down. */
long long secSinceUnixEpoch = (long long)(t / UA_DATETIME_SEC)
- (long long)(UA_DATETIME_UNIX_EPOCH / UA_DATETIME_SEC);
+
+ /* Negative fractions of a second? Remove one full second from the epoch
+ * distance and allow only a positive fraction. */
+ UA_DateTime frac = t % UA_DATETIME_SEC;
+ if(frac < 0) {
+ secSinceUnixEpoch--;
+ frac += UA_DATETIME_SEC;
+ }
+
struct mytm ts;
memset(&ts, 0, sizeof(struct mytm));
__secs_to_tm(secSinceUnixEpoch, &ts);
- dateTimeStruct.sec = (u16)ts.tm_sec;
- dateTimeStruct.min = (u16)ts.tm_min;
- dateTimeStruct.hour = (u16)ts.tm_hour;
- dateTimeStruct.day = (u16)ts.tm_mday;
+
+ UA_DateTimeStruct dateTimeStruct;
+ dateTimeStruct.year = (i16)(ts.tm_year + 1900);
dateTimeStruct.month = (u16)(ts.tm_mon + 1);
- dateTimeStruct.year = (u16)(ts.tm_year + 1900);
+ dateTimeStruct.day = (u16)ts.tm_mday;
+ dateTimeStruct.hour = (u16)ts.tm_hour;
+ dateTimeStruct.min = (u16)ts.tm_min;
+ dateTimeStruct.sec = (u16)ts.tm_sec;
+ dateTimeStruct.milliSec = (u16)((frac % 10000000) / 10000);
+ dateTimeStruct.microSec = (u16)((frac % 10000) / 10);
+ dateTimeStruct.nanoSec = (u16)((frac % 10) * 100);
return dateTimeStruct;
}
@@ -7771,9 +5392,7 @@ UA_DateTime_fromStruct(UA_DateTimeStruct ts) {
/* Guid */
UA_Boolean
UA_Guid_equal(const UA_Guid *g1, const UA_Guid *g2) {
- if(memcmp(g1, g2, sizeof(UA_Guid)) == 0)
- return true;
- return false;
+ return (guidOrder(g1, g2, NULL) == UA_ORDER_EQ);
}
UA_Guid
@@ -7803,7 +5422,7 @@ UA_ByteString_allocBuffer(UA_ByteString *bs, size_t length) {
if(length == 0)
return UA_STATUSCODE_GOOD;
bs->data = (u8*)UA_malloc(length);
- if(!bs->data)
+ if(UA_UNLIKELY(!bs->data))
return UA_STATUSCODE_BADOUTOFMEMORY;
bs->length = length;
return UA_STATUSCODE_GOOD;
@@ -7855,11 +5474,10 @@ UA_NodeId_isNull(const UA_NodeId *p) {
case UA_NODEIDTYPE_NUMERIC:
return (p->identifier.numeric == 0);
case UA_NODEIDTYPE_STRING:
- return UA_String_equal(&p->identifier.string, &UA_STRING_NULL);
+ case UA_NODEIDTYPE_BYTESTRING:
+ return (p->identifier.string.length == 0); /* Null and empty string */
case UA_NODEIDTYPE_GUID:
return UA_Guid_equal(&p->identifier.guid, &UA_GUID_NULL);
- case UA_NODEIDTYPE_BYTESTRING:
- return UA_ByteString_equal(&p->identifier.byteString, &UA_BYTESTRING_NULL);
}
return false;
}
@@ -7868,81 +5486,39 @@ UA_NodeId_isNull(const UA_NodeId *p) {
UA_Order
UA_NodeId_order(const UA_NodeId *n1, const UA_NodeId *n2) {
/* Compare namespaceIndex */
- if(n1->namespaceIndex < n2->namespaceIndex)
- return UA_ORDER_LESS;
- if(n1->namespaceIndex > n2->namespaceIndex)
- return UA_ORDER_MORE;
+ if(n1->namespaceIndex != n2->namespaceIndex)
+ return (n1->namespaceIndex < n2->namespaceIndex) ? UA_ORDER_LESS : UA_ORDER_MORE;
/* Compare identifierType */
- if(n1->identifierType < n2->identifierType)
- return UA_ORDER_LESS;
- if(n1->identifierType > n2->identifierType)
- return UA_ORDER_MORE;
+ if(n1->identifierType != n2->identifierType)
+ return (n1->identifierType < n2->identifierType) ? UA_ORDER_LESS : UA_ORDER_MORE;
/* Compare the identifier */
switch(n1->identifierType) {
case UA_NODEIDTYPE_NUMERIC:
- if(n1->identifier.numeric < n2->identifier.numeric)
- return UA_ORDER_LESS;
- if(n1->identifier.numeric > n2->identifier.numeric)
- return UA_ORDER_MORE;
- break;
- case UA_NODEIDTYPE_GUID:
- if(n1->identifier.guid.data1 < n2->identifier.guid.data1) {
- return UA_ORDER_LESS;
- } else if(n1->identifier.guid.data1 > n2->identifier.guid.data1) {
- return UA_ORDER_MORE;
- } else if(n1->identifier.guid.data2 < n2->identifier.guid.data2) {
- return UA_ORDER_LESS;
- } else if(n1->identifier.guid.data2 > n2->identifier.guid.data2) {
- return UA_ORDER_MORE;
- } else if(n1->identifier.guid.data3 < n2->identifier.guid.data3) {
- return UA_ORDER_LESS;
- } else if(n1->identifier.guid.data3 > n2->identifier.guid.data3) {
- return UA_ORDER_MORE;
- } else {
- int cmp = memcmp(n1->identifier.guid.data4, n2->identifier.guid.data4, 8);
-
- if(cmp < 0) return UA_ORDER_LESS;
- if(cmp > 0) return UA_ORDER_MORE;
+ default:
+ if(n1->identifier.numeric != n2->identifier.numeric)
+ return (n1->identifier.numeric < n2->identifier.numeric) ?
+ UA_ORDER_LESS : UA_ORDER_MORE;
+ return UA_ORDER_EQ;
- }
+ case UA_NODEIDTYPE_GUID:
+ return guidOrder(&n1->identifier.guid, &n2->identifier.guid, NULL);
- break;
case UA_NODEIDTYPE_STRING:
- case UA_NODEIDTYPE_BYTESTRING: {
- size_t minLength = UA_MIN(n1->identifier.string.length, n2->identifier.string.length);
- int cmp = strncmp((const char*)n1->identifier.string.data,
- (const char*)n2->identifier.string.data,
- minLength);
- if(cmp < 0)
- return UA_ORDER_LESS;
- if(cmp > 0)
- return UA_ORDER_MORE;
-
- if(n1->identifier.string.length < n2->identifier.string.length)
- return UA_ORDER_LESS;
- if(n1->identifier.string.length > n2->identifier.string.length)
- return UA_ORDER_MORE;
- break;
- }
- default:
- break;
+ case UA_NODEIDTYPE_BYTESTRING:
+ return stringOrder(&n1->identifier.string, &n2->identifier.string, NULL);
}
-
- return UA_ORDER_EQ;
}
-/* FNV non-cryptographic hash function. See
- * https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function */
-#define FNV_PRIME_32 16777619
+/* sdbm-hash (http://www.cse.yorku.ca/~oz/hash.html) */
u32
-UA_ByteString_hash(u32 fnv, const u8 *buf, size_t size) {
- for(size_t i = 0; i < size; ++i) {
- fnv = fnv ^ (buf[i]);
- fnv = fnv * FNV_PRIME_32;
- }
- return fnv;
+UA_ByteString_hash(u32 initialHashValue,
+ const u8 *data, size_t size) {
+ u32 h = initialHashValue;
+ for(size_t i = 0; i < size; i++)
+ h = data[i] + (h << 6) + (h << 16) - h;
+ return h;
}
u32
@@ -7950,13 +5526,15 @@ UA_NodeId_hash(const UA_NodeId *n) {
switch(n->identifierType) {
case UA_NODEIDTYPE_NUMERIC:
default:
- // shift knuth multiplication to use highest 32 bits and after addition make sure we don't have an integer overflow
- return (u32)((n->namespaceIndex + ((n->identifier.numeric * (u64)2654435761) >> (32))) & UINT32_C(4294967295)); /* Knuth's multiplicative hashing */
+ return UA_ByteString_hash(n->namespaceIndex, (const u8*)&n->identifier.numeric,
+ sizeof(UA_UInt32));
case UA_NODEIDTYPE_STRING:
case UA_NODEIDTYPE_BYTESTRING:
- return UA_ByteString_hash(n->namespaceIndex, n->identifier.string.data, n->identifier.string.length);
+ return UA_ByteString_hash(n->namespaceIndex, n->identifier.string.data,
+ n->identifier.string.length);
case UA_NODEIDTYPE_GUID:
- return UA_ByteString_hash(n->namespaceIndex, (const u8*)&n->identifier.guid, sizeof(UA_Guid));
+ return UA_ByteString_hash(n->namespaceIndex, (const u8*)&n->identifier.guid,
+ sizeof(UA_Guid));
}
}
@@ -7976,34 +5554,30 @@ ExpandedNodeId_copy(UA_ExpandedNodeId const *src, UA_ExpandedNodeId *dst,
return retval;
}
+UA_Boolean
+UA_ExpandedNodeId_isLocal(const UA_ExpandedNodeId *n) {
+ return (n->namespaceUri.length == 0 && n->serverIndex == 0);
+}
+
UA_Order
UA_ExpandedNodeId_order(const UA_ExpandedNodeId *n1,
const UA_ExpandedNodeId *n2) {
- if(n1->serverIndex > n2->serverIndex)
- return UA_ORDER_MORE;
- if(n1->serverIndex < n2->serverIndex)
- return UA_ORDER_LESS;
- if(n1->namespaceUri.length > 0) {
- if(n1->namespaceUri.length > n2->namespaceUri.length)
- return UA_ORDER_MORE;
- if(n1->namespaceUri.length < n2->namespaceUri.length)
- return UA_ORDER_LESS;
- int cmp = strncmp((const char*)n1->namespaceUri.data,
- (const char*)n2->namespaceUri.data,
- n1->namespaceUri.length);
- if(cmp < 0)
- return UA_ORDER_LESS;
- if(cmp > 0)
- return UA_ORDER_MORE;
- }
+ if(n1->serverIndex != n2->serverIndex)
+ return (n1->serverIndex < n2->serverIndex) ? UA_ORDER_LESS : UA_ORDER_MORE;
+ UA_Order o = stringOrder(&n1->namespaceUri, &n2->namespaceUri, NULL);
+ if(o != UA_ORDER_EQ)
+ return o;
return UA_NodeId_order(&n1->nodeId, &n2->nodeId);
}
u32
UA_ExpandedNodeId_hash(const UA_ExpandedNodeId *n) {
u32 h = UA_NodeId_hash(&n->nodeId);
- h = UA_ByteString_hash(h, (const UA_Byte*)&n->serverIndex, 4);
- return UA_ByteString_hash(h, n->namespaceUri.data, n->namespaceUri.length);
+ if(n->serverIndex != 0)
+ h = UA_ByteString_hash(h, (const UA_Byte*)&n->serverIndex, 4);
+ if(n->namespaceUri.length != 0)
+ h = UA_ByteString_hash(h, n->namespaceUri.data, n->namespaceUri.length);
+ return h;
}
/* ExtensionObject */
@@ -8054,17 +5628,65 @@ ExtensionObject_copy(UA_ExtensionObject const *src, UA_ExtensionObject *dst,
return retval;
}
+void
+UA_ExtensionObject_setValue(UA_ExtensionObject *eo,
+ void * UA_RESTRICT p,
+ const UA_DataType *type) {
+ UA_ExtensionObject_init(eo);
+ eo->content.decoded.data = p;
+ eo->content.decoded.type = type;
+ eo->encoding = UA_EXTENSIONOBJECT_DECODED;
+}
+
+void
+UA_ExtensionObject_setValueNoDelete(UA_ExtensionObject *eo,
+ void * UA_RESTRICT p,
+ const UA_DataType *type) {
+ UA_ExtensionObject_init(eo);
+ eo->content.decoded.data = p;
+ eo->content.decoded.type = type;
+ eo->encoding = UA_EXTENSIONOBJECT_DECODED_NODELETE;
+}
+
+UA_StatusCode
+UA_ExtensionObject_setValueCopy(UA_ExtensionObject *eo,
+ void * UA_RESTRICT p,
+ const UA_DataType *type) {
+ UA_ExtensionObject_init(eo);
+
+ /* Make a copy of the value */
+ void *val = UA_malloc(type->memSize);
+ if(UA_UNLIKELY(!val))
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ UA_StatusCode res = UA_copy(p, val, type);
+ if(UA_UNLIKELY(res != UA_STATUSCODE_GOOD)) {
+ UA_free(val);
+ return res;
+ }
+
+ /* Set the ExtensionObject */
+ eo->content.decoded.data = val;
+ eo->content.decoded.type = type;
+ eo->encoding = UA_EXTENSIONOBJECT_DECODED;
+ return UA_STATUSCODE_GOOD;
+}
+
/* Variant */
static void
Variant_clear(UA_Variant *p, const UA_DataType *_) {
- if(p->storageType != UA_VARIANT_DATA)
+ /* The content is "borrowed" */
+ if(p->storageType == UA_VARIANT_DATA_NODELETE)
return;
+
+ /* Delete the value */
if(p->type && p->data > UA_EMPTY_ARRAY_SENTINEL) {
if(p->arrayLength == 0)
p->arrayLength = 1;
UA_Array_delete(p->data, p->arrayLength, p->type);
p->data = NULL;
}
+
+ /* Delete the array dimensions */
if((void*)p->arrayDimensions > UA_EMPTY_ARRAY_SENTINEL)
UA_free(p->arrayDimensions);
}
@@ -8100,13 +5722,13 @@ UA_Variant_setScalar(UA_Variant *v, void * UA_RESTRICT p,
}
UA_StatusCode
-UA_Variant_setScalarCopy(UA_Variant *v, const void *p,
+UA_Variant_setScalarCopy(UA_Variant *v, const void * UA_RESTRICT p,
const UA_DataType *type) {
void *n = UA_malloc(type->memSize);
- if(!n)
+ if(UA_UNLIKELY(!n))
return UA_STATUSCODE_BADOUTOFMEMORY;
UA_StatusCode retval = UA_copy(p, n, type);
- if(retval != UA_STATUSCODE_GOOD) {
+ if(UA_UNLIKELY(retval != UA_STATUSCODE_GOOD)) {
UA_free(n);
//cppcheck-suppress memleak
return retval;
@@ -8125,7 +5747,7 @@ void UA_Variant_setArray(UA_Variant *v, void * UA_RESTRICT array,
}
UA_StatusCode
-UA_Variant_setArrayCopy(UA_Variant *v, const void *array,
+UA_Variant_setArrayCopy(UA_Variant *v, const void * UA_RESTRICT array,
size_t arraySize, const UA_DataType *type) {
UA_Variant_init(v);
UA_StatusCode retval = UA_Array_copy(array, arraySize, &v->data, type);
@@ -8136,42 +5758,36 @@ UA_Variant_setArrayCopy(UA_Variant *v, const void *array,
return UA_STATUSCODE_GOOD;
}
-/* Test if a range is compatible with a variant. If yes, the following values
- * are set:
- * - total: how many elements are in the range
- * - block: how big is each contiguous block of elements in the variant that
- * maps into the range
- * - stride: how many elements are between the blocks (beginning to beginning)
- * - first: where does the first block begin */
+/* Test if a range is compatible with a variant. This may adjust the upper bound
+ * (max) in order to fit the variant. */
static UA_StatusCode
-computeStrides(const UA_Variant *v, const UA_NumericRange range,
- size_t *total, size_t *block, size_t *stride, size_t *first) {
+checkAdjustRange(const UA_Variant *v, UA_NumericRange *range) {
/* Test for max array size (64bit only) */
#if (SIZE_MAX > 0xffffffff)
if(v->arrayLength > UA_UINT32_MAX)
return UA_STATUSCODE_BADINTERNALERROR;
#endif
-
- /* Test the integrity of the source variant dimensions, make dimensions
- * vector of one dimension if none defined */
u32 arrayLength = (u32)v->arrayLength;
- const u32 *dims = &arrayLength;
- size_t dims_count = 1;
- if(v->arrayDimensionsSize > 0) {
- size_t elements = 1;
- dims_count = v->arrayDimensionsSize;
- dims = (u32*)v->arrayDimensions;
- for(size_t i = 0; i < dims_count; ++i)
- elements *= dims[i];
- if(elements != v->arrayLength)
- return UA_STATUSCODE_BADINTERNALERROR;
+
+ /* Assume one array dimension if none defined */
+ const u32 *dims = v->arrayDimensions;
+ size_t dims_count = v->arrayDimensionsSize;
+ if(v->arrayDimensionsSize == 0) {
+ dims_count = 1;
+ dims = &arrayLength;
}
- UA_assert(dims_count > 0);
- /* Upper bound of the dimensions for stack-allocation */
- if(dims_count > UA_MAX_ARRAY_DIMS)
+ /* Does the range match the dimension of the variant? */
+ if(range->dimensionsSize != dims_count)
+ return UA_STATUSCODE_BADINDEXRANGENODATA;
+
+ /* Check that the number of elements in the variant matches the array
+ * dimensions */
+ size_t elements = 1;
+ for(size_t i = 0; i < dims_count; ++i)
+ elements *= dims[i];
+ if(elements != v->arrayLength)
return UA_STATUSCODE_BADINTERNALERROR;
- UA_UInt32 realmax[UA_MAX_ARRAY_DIMS];
/* Test the integrity of the range and compute the max index used for every
* dimension. The standard says in Part 4, Section 7.22:
@@ -8179,25 +5795,44 @@ computeStrides(const UA_Variant *v, const UA_NumericRange range,
* When reading a value, the indexes may not specify a range that is within
* the bounds of the array. The Server shall return a partial result if some
* elements exist within the range. */
- size_t count = 1;
- if(range.dimensionsSize != dims_count)
- return UA_STATUSCODE_BADINDEXRANGENODATA;
for(size_t i = 0; i < dims_count; ++i) {
- if(range.dimensions[i].min > range.dimensions[i].max)
+ if(range->dimensions[i].min > range->dimensions[i].max)
return UA_STATUSCODE_BADINDEXRANGEINVALID;
- if(range.dimensions[i].min >= dims[i])
+ if(range->dimensions[i].min >= dims[i])
return UA_STATUSCODE_BADINDEXRANGENODATA;
- if(range.dimensions[i].max < dims[i])
- realmax[i] = range.dimensions[i].max;
- else
- realmax[i] = dims[i] - 1;
-
- count *= (realmax[i] - range.dimensions[i].min) + 1;
+ /* Reduce the max to fit the variant */
+ if(range->dimensions[i].max >= dims[i])
+ range->dimensions[i].max = dims[i] - 1;
}
+ return UA_STATUSCODE_GOOD;
+}
+
+/* Computes the stride for copying the range elements.
+ * - total: how many elements are in the range
+ * - block: how big is each contiguous block of elements in the variant that
+ * maps into the range
+ * - stride: how many elements are between the blocks (beginning to beginning)
+ * - first: where does the first block begin */
+static void
+computeStrides(const UA_Variant *v, const UA_NumericRange range,
+ size_t *total, size_t *block, size_t *stride, size_t *first) {
+ /* Number of total elements to be copied */
+ size_t count = 1;
+ for(size_t i = 0; i < range.dimensionsSize; ++i)
+ count *= (range.dimensions[i].max - range.dimensions[i].min) + 1;
*total = count;
+ /* Assume one array dimension if none defined */
+ u32 arrayLength = (u32)v->arrayLength;
+ const u32 *dims = v->arrayDimensions;
+ size_t dims_count = v->arrayDimensionsSize;
+ if(v->arrayDimensionsSize == 0) {
+ dims_count = 1;
+ dims = &arrayLength;
+ }
+
/* Compute the stride length and the position of the first element */
*block = count; /* Assume the range describes the entire array. */
*stride = v->arrayLength; /* So it can be copied as a contiguous block. */
@@ -8206,7 +5841,7 @@ computeStrides(const UA_Variant *v, const UA_NumericRange range,
UA_Boolean found_contiguous = false;
for(size_t k = dims_count; k > 0;) {
--k;
- size_t dimrange = 1 + realmax[k] - range.dimensions[k].min;
+ size_t dimrange = 1 + range.dimensions[k].max - range.dimensions[k].min;
if(!found_contiguous && dimrange != dims[k]) {
/* Found the maximum block that can be copied contiguously */
found_contiguous = true;
@@ -8216,7 +5851,6 @@ computeStrides(const UA_Variant *v, const UA_NumericRange range,
*first += running_dimssize * range.dimensions[k].min;
running_dimssize *= dims[k];
}
- return UA_STATUSCODE_GOOD;
}
/* Is the type string-like? */
@@ -8253,19 +5887,30 @@ copySubString(const UA_String *src, UA_String *dst,
}
UA_StatusCode
-UA_Variant_copyRange(const UA_Variant *src, UA_Variant *dst,
+UA_Variant_copyRange(const UA_Variant *src, UA_Variant * UA_RESTRICT dst,
const UA_NumericRange range) {
if(!src->type)
return UA_STATUSCODE_BADINVALIDARGUMENT;
+
UA_Boolean isScalar = UA_Variant_isScalar(src);
UA_Boolean stringLike = isStringLike(src->type);
- UA_Variant arraySrc;
+
+ /* Upper bound of the dimensions for stack-allocation */
+ if(range.dimensionsSize > UA_MAX_ARRAY_DIMS)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ /* Copy the const range to a mutable stack location */
+ UA_NumericRangeDimension thisrangedims[UA_MAX_ARRAY_DIMS];
+ memcpy(thisrangedims, range.dimensions, sizeof(UA_NumericRangeDimension) * range.dimensionsSize);
+ UA_NumericRange thisrange = {range.dimensionsSize, thisrangedims};
+
+ UA_NumericRangeDimension scalarThisDimension = {0,0}; /* a single entry */
+ UA_NumericRange nextrange = {0, NULL};
/* Extract the range for copying at this level. The remaining range is dealt
* with in the "scalar" type that may define an array by itself (string,
* variant, ...). */
- UA_NumericRange thisrange, nextrange;
- UA_NumericRangeDimension scalarThisDimension = {0,0}; /* a single entry */
+ UA_Variant arraySrc;
if(isScalar) {
/* Replace scalar src with array of length 1 */
arraySrc = *src;
@@ -8282,19 +5927,19 @@ UA_Variant_copyRange(const UA_Variant *src, UA_Variant *dst,
dims = 1;
if(dims > range.dimensionsSize)
return UA_STATUSCODE_BADINDEXRANGEINVALID;
- thisrange = range;
thisrange.dimensionsSize = dims;
nextrange.dimensions = &range.dimensions[dims];
nextrange.dimensionsSize = range.dimensionsSize - dims;
}
- /* Compute the strides */
- size_t count, block, stride, first;
- UA_StatusCode retval = computeStrides(src, thisrange, &count,
- &block, &stride, &first);
+ UA_StatusCode retval = checkAdjustRange(src, &thisrange);
if(retval != UA_STATUSCODE_GOOD)
return retval;
+ /* Compute the strides */
+ size_t count, block, stride, first;
+ computeStrides(src, thisrange, &count, &block, &stride, &first);
+
/* Allocate the array */
UA_Variant_init(dst);
dst->data = UA_Array_new(count, src->type);
@@ -8387,12 +6032,25 @@ UA_Variant_copyRange(const UA_Variant *src, UA_Variant *dst,
static UA_StatusCode
Variant_setRange(UA_Variant *v, void *array, size_t arraySize,
const UA_NumericRange range, UA_Boolean copy) {
- /* Compute the strides */
- size_t count, block, stride, first;
- UA_StatusCode retval = computeStrides(v, range, &count,
- &block, &stride, &first);
+ if(!v->type)
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+
+ /* Upper bound of the dimensions for stack-allocation */
+ if(range.dimensionsSize > UA_MAX_ARRAY_DIMS)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ /* Copy the const range to a mutable stack location */
+ UA_NumericRangeDimension thisrangedims[UA_MAX_ARRAY_DIMS];
+ memcpy(thisrangedims, range.dimensions, sizeof(UA_NumericRangeDimension) * range.dimensionsSize);
+ UA_NumericRange thisrange = {range.dimensionsSize, thisrangedims};
+
+ UA_StatusCode retval = checkAdjustRange(v, &thisrange);
if(retval != UA_STATUSCODE_GOOD)
return retval;
+
+ /* Compute the strides */
+ size_t count, block, stride, first;
+ computeStrides(v, range, &count, &block, &stride, &first);
if(count != arraySize)
return UA_STATUSCODE_BADINDEXRANGEINVALID;
@@ -8433,7 +6091,7 @@ UA_Variant_setRange(UA_Variant *v, void * UA_RESTRICT array,
}
UA_StatusCode
-UA_Variant_setRangeCopy(UA_Variant *v, const void *array,
+UA_Variant_setRangeCopy(UA_Variant *v, const void * UA_RESTRICT array,
size_t arraySize, const UA_NumericRange range) {
return Variant_setRange(v, (void*)(uintptr_t)array,
arraySize, range, true);
@@ -8471,6 +6129,17 @@ DataValue_copy(UA_DataValue const *src, UA_DataValue *dst,
return retval;
}
+UA_StatusCode
+UA_DataValue_copyVariantRange(const UA_DataValue *src, UA_DataValue * UA_RESTRICT dst,
+ const UA_NumericRange range) {
+ memcpy(dst, src, sizeof(UA_DataValue));
+ UA_Variant_init(&dst->value);
+ UA_StatusCode retval = UA_Variant_copyRange(&src->value, &dst->value, range);
+ if(retval != UA_STATUSCODE_GOOD)
+ DataValue_clear(dst, NULL);
+ return retval;
+}
+
/* DiagnosticInfo */
static void
DiagnosticInfo_clear(UA_DiagnosticInfo *p, const UA_DataType *_) {
@@ -8491,8 +6160,9 @@ DiagnosticInfo_copy(UA_DiagnosticInfo const *src, UA_DiagnosticInfo *dst,
if(src->hasAdditionalInfo)
retval = UA_String_copy(&src->additionalInfo, &dst->additionalInfo);
if(src->hasInnerDiagnosticInfo && src->innerDiagnosticInfo) {
- dst->innerDiagnosticInfo = (UA_DiagnosticInfo*)UA_malloc(sizeof(UA_DiagnosticInfo));
- if(dst->innerDiagnosticInfo) {
+ dst->innerDiagnosticInfo = (UA_DiagnosticInfo*)
+ UA_malloc(sizeof(UA_DiagnosticInfo));
+ if(UA_LIKELY(dst->innerDiagnosticInfo != NULL)) {
retval |= DiagnosticInfo_copy(src->innerDiagnosticInfo,
dst->innerDiagnosticInfo, NULL);
dst->hasInnerDiagnosticInfo = true;
@@ -8549,10 +6219,9 @@ copyStructure(const void *src, void *dst, const UA_DataType *type) {
UA_StatusCode retval = UA_STATUSCODE_GOOD;
uintptr_t ptrs = (uintptr_t)src;
uintptr_t ptrd = (uintptr_t)dst;
- const UA_DataType *typelists[2] = { UA_TYPES, &type[-type->typeIndex] };
for(size_t i = 0; i < type->membersSize; ++i) {
const UA_DataTypeMember *m = &type->members[i];
- const UA_DataType *mt = &typelists[!m->namespaceZero][m->memberTypeIndex];
+ const UA_DataType *mt = m->memberType;
ptrs += m->padding;
ptrd += m->padding;
if(!m->isOptional) {
@@ -8608,14 +6277,28 @@ copyUnion(const void *src, void *dst, const UA_DataType *type) {
UA_copy((const UA_UInt32 *) ptrs, (UA_UInt32 *) ptrd, &UA_TYPES[UA_TYPES_UINT32]);
if(selection == 0)
return UA_STATUSCODE_GOOD;
- const UA_DataType *typelists[2] = { UA_TYPES, &type[-type->typeIndex] };
const UA_DataTypeMember *m = &type->members[selection-1];
- const UA_DataType *mt = &typelists[!m->namespaceZero][m->memberTypeIndex];
- ptrs += UA_TYPES[UA_TYPES_UINT32].memSize;
- ptrd += UA_TYPES[UA_TYPES_UINT32].memSize;
+ const UA_DataType *mt = m->memberType;
ptrs += m->padding;
ptrd += m->padding;
- return UA_copy((const void *) ptrs, (void *) ptrd, mt);
+
+ UA_StatusCode retval = UA_STATUSCODE_GOOD;
+
+ if (m->isArray) {
+ size_t *dst_size = (size_t*)ptrd;
+ const size_t size = *((const size_t*)ptrs);
+ ptrs += sizeof(size_t);
+ ptrd += sizeof(size_t);
+ retval = UA_Array_copy(*(void* const*)ptrs, size, (void**)ptrd, mt);
+ if(retval == UA_STATUSCODE_GOOD)
+ *dst_size = size;
+ else
+ *dst_size = 0;
+ } else {
+ retval = copyJumpTable[mt->typeKind]((const void *)ptrs, (void *)ptrd, mt);
+ }
+
+ return retval;
}
static UA_StatusCode
@@ -8669,10 +6352,9 @@ UA_copy(const void *src, void *dst, const UA_DataType *type) {
static void
clearStructure(void *p, const UA_DataType *type) {
uintptr_t ptr = (uintptr_t)p;
- const UA_DataType *typelists[2] = { UA_TYPES, &type[-type->typeIndex] };
for(size_t i = 0; i < type->membersSize; ++i) {
const UA_DataTypeMember *m = &type->members[i];
- const UA_DataType *mt = &typelists[!m->namespaceZero][m->memberTypeIndex];
+ const UA_DataType *mt = m->memberType;
ptr += m->padding;
if(!m->isOptional) {
if(!m->isArray) {
@@ -8712,12 +6394,16 @@ clearUnion(void *p, const UA_DataType *type) {
UA_UInt32 selection = *(UA_UInt32 *)ptr;
if(selection == 0)
return;
- const UA_DataType *typelists[2] = { UA_TYPES, &type[-type->typeIndex] };
const UA_DataTypeMember *m = &type->members[selection-1];
- const UA_DataType *mt = &typelists[!m->namespaceZero][m->memberTypeIndex];
- ptr += UA_TYPES[UA_TYPES_UINT32].memSize;
+ const UA_DataType *mt = m->memberType;
ptr += m->padding;
- UA_clear((void *) ptr, mt);
+ if (m->isArray) {
+ size_t length = *(size_t *)ptr;
+ ptr += sizeof(size_t);
+ UA_Array_delete(*(void **)ptr, length, mt);
+ } else {
+ UA_clear((void *) ptr, mt);
+ }
}
static void nopClear(void *p, const UA_DataType *type) { }
@@ -8770,6 +6456,427 @@ UA_delete(void *p, const UA_DataType *type) {
}
/******************/
+/* Value Ordering */
+/******************/
+
+#define UA_NUMERICORDER(NAME, TYPE) \
+ static UA_Order \
+ NAME(const TYPE *p1, const TYPE *p2, const UA_DataType *type) { \
+ if(*p1 != *p2) \
+ return (*p1 < *p2) ? UA_ORDER_LESS : UA_ORDER_MORE; \
+ return UA_ORDER_EQ; \
+ }
+
+UA_NUMERICORDER(booleanOrder, UA_Boolean)
+UA_NUMERICORDER(sByteOrder, UA_SByte)
+UA_NUMERICORDER(byteOrder, UA_Byte)
+UA_NUMERICORDER(int16Order, UA_Int16)
+UA_NUMERICORDER(uInt16Order, UA_UInt16)
+UA_NUMERICORDER(int32Order, UA_Int32)
+UA_NUMERICORDER(uInt32Order, UA_UInt32)
+UA_NUMERICORDER(int64Order, UA_Int64)
+UA_NUMERICORDER(uInt64Order, UA_UInt64)
+
+#define UA_FLOATORDER(NAME, TYPE) \
+ static UA_Order \
+ NAME(const TYPE *p1, const TYPE *p2, const UA_DataType *type) { \
+ if(*p1 != *p2) { \
+ /* p1 is NaN */ \
+ if(*p1 != *p1) { \
+ if(*p2 != *p2) \
+ return UA_ORDER_EQ; \
+ return UA_ORDER_LESS; \
+ } \
+ /* p2 is NaN */ \
+ if(*p2 != *p2) \
+ return UA_ORDER_MORE; \
+ return (*p1 < *p2) ? UA_ORDER_LESS : UA_ORDER_MORE; \
+ } \
+ return UA_ORDER_EQ; \
+ }
+
+UA_FLOATORDER(floatOrder, UA_Float)
+UA_FLOATORDER(doubleOrder, UA_Double)
+
+static UA_Order
+guidOrder(const UA_Guid *p1, const UA_Guid *p2, const UA_DataType *type) {
+ if(p1->data1 != p2->data1)
+ return (p1->data1 < p2->data1) ? UA_ORDER_LESS : UA_ORDER_MORE;
+ if(p1->data2 != p2->data2)
+ return (p1->data2 < p2->data2) ? UA_ORDER_LESS : UA_ORDER_MORE;
+ if(p1->data3 != p2->data3)
+ return (p1->data3 < p2->data3) ? UA_ORDER_LESS : UA_ORDER_MORE;
+ int cmp = memcmp(p1->data4, p2->data4, 8);
+ if(cmp != 0)
+ return (cmp < 0) ? UA_ORDER_LESS : UA_ORDER_MORE;
+ return UA_ORDER_EQ;
+}
+
+static UA_Order
+stringOrder(const UA_String *p1, const UA_String *p2, const UA_DataType *type) {
+ if(p1->length != p2->length)
+ return (p1->length < p2->length) ? UA_ORDER_LESS : UA_ORDER_MORE;
+ /* For zero-length arrays, every pointer not NULL is considered a
+ * UA_EMPTY_ARRAY_SENTINEL. */
+ if(p1->data == p2->data) return UA_ORDER_EQ;
+ if(p1->data == NULL) return UA_ORDER_LESS;
+ if(p2->data == NULL) return UA_ORDER_MORE;
+ int cmp = memcmp((const char*)p1->data, (const char*)p2->data, p1->length);
+ if(cmp != 0)
+ return (cmp < 0) ? UA_ORDER_LESS : UA_ORDER_MORE;
+ return UA_ORDER_EQ;
+}
+
+static UA_Order
+nodeIdOrder(const UA_NodeId *p1, const UA_NodeId *p2, const UA_DataType *type) {
+ return UA_NodeId_order(p1, p2);
+}
+
+static UA_Order
+expandedNodeIdOrder(const UA_ExpandedNodeId *p1, const UA_ExpandedNodeId *p2,
+ const UA_DataType *type) {
+ return UA_ExpandedNodeId_order(p1, p2);
+}
+
+static UA_Order
+qualifiedNameOrder(const UA_QualifiedName *p1, const UA_QualifiedName *p2,
+ const UA_DataType *type) {
+ if(p1->namespaceIndex != p2->namespaceIndex)
+ return (p1->namespaceIndex < p2->namespaceIndex) ? UA_ORDER_LESS : UA_ORDER_MORE;
+ return stringOrder(&p1->name, &p2->name, NULL);
+}
+
+static UA_Order
+localizedTextOrder(const UA_LocalizedText *p1, const UA_LocalizedText *p2,
+ const UA_DataType *type) {
+ UA_Order o = stringOrder(&p1->locale, &p2->locale, NULL);
+ if(o != UA_ORDER_EQ)
+ return o;
+ return stringOrder(&p1->text, &p2->text, NULL);
+}
+
+static UA_Order
+extensionObjectOrder(const UA_ExtensionObject *p1, const UA_ExtensionObject *p2,
+ const UA_DataType *type) {
+ UA_ExtensionObjectEncoding enc1 = p1->encoding;
+ UA_ExtensionObjectEncoding enc2 = p2->encoding;
+ if(enc1 > UA_EXTENSIONOBJECT_DECODED)
+ enc1 = UA_EXTENSIONOBJECT_DECODED;
+ if(enc2 > UA_EXTENSIONOBJECT_DECODED)
+ enc2 = UA_EXTENSIONOBJECT_DECODED;
+ if(enc1 != enc2)
+ return (enc1 < enc2) ? UA_ORDER_LESS : UA_ORDER_MORE;
+
+ switch(enc1) {
+ case UA_EXTENSIONOBJECT_ENCODED_NOBODY:
+ return UA_ORDER_EQ;
+
+ case UA_EXTENSIONOBJECT_ENCODED_BYTESTRING:
+ case UA_EXTENSIONOBJECT_ENCODED_XML: {
+ UA_Order o = UA_NodeId_order(&p1->content.encoded.typeId,
+ &p2->content.encoded.typeId);
+ if(o == UA_ORDER_EQ)
+ o = stringOrder((const UA_String*)&p1->content.encoded.body,
+ (const UA_String*)&p2->content.encoded.body, NULL);
+ return o;
+ }
+
+ case UA_EXTENSIONOBJECT_DECODED:
+ default: {
+ const UA_DataType *type1 = p1->content.decoded.type;
+ const UA_DataType *type2 = p1->content.decoded.type;
+ if(type1 != type2)
+ return ((uintptr_t)type1 < (uintptr_t)type2) ? UA_ORDER_LESS : UA_ORDER_MORE;
+ if(!type1)
+ return UA_ORDER_EQ;
+ return orderJumpTable[type1->typeKind]
+ (p1->content.decoded.data, p2->content.decoded.data, type1);
+ }
+ }
+}
+
+static UA_Order
+arrayOrder(const void *p1, size_t p1Length, const void *p2, size_t p2Length,
+ const UA_DataType *type) {
+ if(p1Length != p2Length)
+ return (p1Length < p2Length) ? UA_ORDER_LESS : UA_ORDER_MORE;
+ /* For zero-length arrays, every pointer not NULL is considered a
+ * UA_EMPTY_ARRAY_SENTINEL. */
+ if(p1 == p2) return UA_ORDER_EQ;
+ if(p1 == NULL) return UA_ORDER_LESS;
+ if(p2 == NULL) return UA_ORDER_MORE;
+ uintptr_t u1 = (uintptr_t)p1;
+ uintptr_t u2 = (uintptr_t)p2;
+ for(size_t i = 0; i < p1Length; i++) {
+ UA_Order o = orderJumpTable[type->typeKind]((const void*)u1, (const void*)u2, type);
+ if(o != UA_ORDER_EQ)
+ return o;
+ u1 += type->memSize;
+ u2 += type->memSize;
+ }
+ return UA_ORDER_EQ;
+}
+
+static UA_Order
+variantOrder(const UA_Variant *p1, const UA_Variant *p2,
+ const UA_DataType *type) {
+ if(p1->type != p2->type)
+ return ((uintptr_t)p1->type < (uintptr_t)p2->type) ? UA_ORDER_LESS : UA_ORDER_MORE;
+
+ UA_Order o;
+ if(p1->type != NULL) {
+ /* Check if both variants are scalars or arrays */
+ UA_Boolean s1 = UA_Variant_isScalar(p1);
+ UA_Boolean s2 = UA_Variant_isScalar(p2);
+ if(s1 != s2)
+ return s1 ? UA_ORDER_LESS : UA_ORDER_MORE;
+ if(s1) {
+ o = orderJumpTable[p1->type->typeKind](p1->data, p2->data, p1->type);
+ } else {
+ /* Mismatching array length? */
+ if(p1->arrayLength != p2->arrayLength)
+ return (p1->arrayLength < p2->arrayLength) ? UA_ORDER_LESS : UA_ORDER_MORE;
+ o = arrayOrder(p1->data, p1->arrayLength, p2->data, p2->arrayLength, p1->type);
+ }
+ if(o != UA_ORDER_EQ)
+ return o;
+ }
+
+ if(p1->arrayDimensionsSize != p2->arrayDimensionsSize)
+ return (p1->arrayDimensionsSize < p2->arrayDimensionsSize) ?
+ UA_ORDER_LESS : UA_ORDER_MORE;
+ o = UA_ORDER_EQ;
+ if(p1->arrayDimensionsSize > 0)
+ o = arrayOrder(p1->arrayDimensions, p1->arrayDimensionsSize,
+ p2->arrayDimensions, p2->arrayDimensionsSize,
+ &UA_TYPES[UA_TYPES_UINT32]);
+ return o;
+}
+
+static UA_Order
+dataValueOrder(const UA_DataValue *p1, const UA_DataValue *p2,
+ const UA_DataType *type) {
+ /* Value */
+ if(p1->hasValue != p2->hasValue)
+ return (!p1->hasValue) ? UA_ORDER_LESS : UA_ORDER_MORE;
+ if(p1->hasValue) {
+ UA_Order o = variantOrder(&p1->value, &p2->value, NULL);
+ if(o != UA_ORDER_EQ)
+ return o;
+ }
+
+ /* Status */
+ if(p1->hasStatus != p2->hasStatus)
+ return (!p1->hasStatus) ? UA_ORDER_LESS : UA_ORDER_MORE;
+ if(p1->hasStatus && p1->status != p2->status)
+ return (p1->status < p2->status) ? UA_ORDER_LESS : UA_ORDER_MORE;
+
+ /* SourceTimestamp */
+ if(p1->hasSourceTimestamp != p2->hasSourceTimestamp)
+ return (!p1->hasSourceTimestamp) ? UA_ORDER_LESS : UA_ORDER_MORE;
+ if(p1->hasSourceTimestamp && p1->sourceTimestamp != p2->sourceTimestamp)
+ return (p1->sourceTimestamp < p2->sourceTimestamp) ? UA_ORDER_LESS : UA_ORDER_MORE;
+
+ /* ServerTimestamp */
+ if(p1->hasServerTimestamp != p2->hasServerTimestamp)
+ return (!p1->hasServerTimestamp) ? UA_ORDER_LESS : UA_ORDER_MORE;
+ if(p1->hasServerTimestamp && p1->serverTimestamp != p2->serverTimestamp)
+ return (p1->serverTimestamp < p2->serverTimestamp) ? UA_ORDER_LESS : UA_ORDER_MORE;
+
+ /* SourcePicoseconds */
+ if(p1->hasSourcePicoseconds != p2->hasSourcePicoseconds)
+ return (!p1->hasSourcePicoseconds) ? UA_ORDER_LESS : UA_ORDER_MORE;
+ if(p1->hasSourcePicoseconds && p1->sourcePicoseconds != p2->sourcePicoseconds)
+ return (p1->sourcePicoseconds < p2->sourcePicoseconds) ?
+ UA_ORDER_LESS : UA_ORDER_MORE;
+
+ /* ServerPicoseconds */
+ if(p1->hasServerPicoseconds != p2->hasServerPicoseconds)
+ return (!p1->hasServerPicoseconds) ? UA_ORDER_LESS : UA_ORDER_MORE;
+ if(p1->hasServerPicoseconds && p1->serverPicoseconds != p2->serverPicoseconds)
+ return (p1->serverPicoseconds < p2->serverPicoseconds) ?
+ UA_ORDER_LESS : UA_ORDER_MORE;
+
+ return UA_ORDER_EQ;
+}
+
+static UA_Order
+diagnosticInfoOrder(const UA_DiagnosticInfo *p1, const UA_DiagnosticInfo *p2,
+ const UA_DataType *type) {
+ /* SymbolicId */
+ if(p1->hasSymbolicId != p2->hasSymbolicId)
+ return (!p1->hasSymbolicId) ? UA_ORDER_LESS : UA_ORDER_MORE;
+ if(p1->hasSymbolicId && p1->symbolicId != p2->symbolicId)
+ return (p1->symbolicId < p2->symbolicId) ? UA_ORDER_LESS : UA_ORDER_MORE;
+
+ /* NamespaceUri */
+ if(p1->hasNamespaceUri != p2->hasNamespaceUri)
+ return (!p1->hasNamespaceUri) ? UA_ORDER_LESS : UA_ORDER_MORE;
+ if(p1->hasNamespaceUri && p1->namespaceUri != p2->namespaceUri)
+ return (p1->namespaceUri < p2->namespaceUri) ? UA_ORDER_LESS : UA_ORDER_MORE;
+
+ /* LocalizedText */
+ if(p1->hasLocalizedText != p2->hasLocalizedText)
+ return (!p1->hasLocalizedText) ? UA_ORDER_LESS : UA_ORDER_MORE;
+ if(p1->hasLocalizedText && p1->localizedText != p2->localizedText)
+ return (p1->localizedText < p2->localizedText) ? UA_ORDER_LESS : UA_ORDER_MORE;
+
+ /* Locale */
+ if(p1->hasLocale != p2->hasLocale)
+ return (!p1->hasLocale) ? UA_ORDER_LESS : UA_ORDER_MORE;
+ if(p1->hasLocale && p1->locale != p2->locale)
+ return (p1->locale < p2->locale) ? UA_ORDER_LESS : UA_ORDER_MORE;
+
+ /* AdditionalInfo */
+ if(p1->hasAdditionalInfo != p2->hasAdditionalInfo)
+ return (!p1->hasAdditionalInfo) ? UA_ORDER_LESS : UA_ORDER_MORE;
+ if(p1->hasAdditionalInfo) {
+ UA_Order o = stringOrder(&p1->additionalInfo, &p2->additionalInfo, NULL);
+ if(o != UA_ORDER_EQ)
+ return o;
+ }
+
+ /* InnerStatusCode */
+ if(p1->hasInnerStatusCode != p2->hasInnerStatusCode)
+ return (!p1->hasInnerStatusCode) ? UA_ORDER_LESS : UA_ORDER_MORE;
+ if(p1->hasInnerStatusCode && p1->innerStatusCode != p2->innerStatusCode)
+ return (p1->innerStatusCode < p2->innerStatusCode) ? UA_ORDER_LESS : UA_ORDER_MORE;
+
+ /* InnerDiagnosticInfo */
+ if(p1->hasInnerDiagnosticInfo != p2->hasInnerDiagnosticInfo)
+ return (!p1->hasInnerDiagnosticInfo) ? UA_ORDER_LESS : UA_ORDER_MORE;
+ if(p1->innerDiagnosticInfo == p2->innerDiagnosticInfo)
+ return UA_ORDER_EQ;
+ if(!p1->innerDiagnosticInfo || !p2->innerDiagnosticInfo)
+ return (!p1->innerDiagnosticInfo) ? UA_ORDER_LESS : UA_ORDER_MORE;
+ return diagnosticInfoOrder(p1->innerDiagnosticInfo, p2->innerDiagnosticInfo, NULL);
+}
+
+static UA_Order
+structureOrder(const void *p1, const void *p2, const UA_DataType *type) {
+ uintptr_t u1 = (uintptr_t)p1;
+ uintptr_t u2 = (uintptr_t)p2;
+ UA_Order o = UA_ORDER_EQ;
+ for(size_t i = 0; i < type->membersSize; ++i) {
+ const UA_DataTypeMember *m = &type->members[i];
+ const UA_DataType *mt = m->memberType;
+ u1 += m->padding;
+ u2 += m->padding;
+ if(!m->isOptional) {
+ if(!m->isArray) {
+ o = orderJumpTable[mt->typeKind]((const void *)u1, (const void *)u2, mt);
+ u1 += mt->memSize;
+ u2 += mt->memSize;
+ } else {
+ size_t size1 = *(size_t*)u1;
+ size_t size2 = *(size_t*)u2;
+ u1 += sizeof(size_t);
+ u2 += sizeof(size_t);
+ o = arrayOrder(*(void* const*)u1, size1, *(void* const*)u2, size2, mt);
+ u1 += sizeof(void*);
+ u2 += sizeof(void*);
+ }
+ } else {
+ if(!m->isArray) {
+ const void *pp1 = *(void* const*)u1;
+ const void *pp2 = *(void* const*)u2;
+ if(pp1 == pp2) {
+ o = UA_ORDER_EQ;
+ } else if(pp1 == NULL) {
+ o = UA_ORDER_LESS;
+ } else if(pp2 == NULL) {
+ o = UA_ORDER_MORE;
+ } else {
+ o = orderJumpTable[mt->typeKind](pp1, pp2, mt);
+ }
+ } else {
+ size_t sa1 = *(size_t*)u1;
+ size_t sa2 = *(size_t*)u2;
+ u1 += sizeof(size_t);
+ u2 += sizeof(size_t);
+ o = arrayOrder(*(void* const*)u1, sa1, *(void* const*)u2, sa2, mt);
+ }
+ u1 += sizeof(void*);
+ u2 += sizeof(void*);
+ }
+
+ if(o != UA_ORDER_EQ)
+ break;
+ }
+ return o;
+}
+
+static UA_Order
+unionOrder(const void *p1, const void *p2, const UA_DataType *type) {
+ UA_UInt32 sel1 = *(const UA_UInt32 *)p1;
+ UA_UInt32 sel2 = *(const UA_UInt32 *)p2;
+ if(sel1 != sel2)
+ return (sel1 < sel2) ? UA_ORDER_LESS : UA_ORDER_MORE;
+
+ if(sel1 == 0) {
+ return UA_ORDER_EQ;
+ }
+
+ const UA_DataTypeMember *m = &type->members[sel1-1];
+ const UA_DataType *mt = m->memberType;
+
+ uintptr_t u1 = ((uintptr_t)p1) + m->padding; /* includes switchfield length */
+ uintptr_t u2 = ((uintptr_t)p2) + m->padding;
+ if(m->isArray) {
+ size_t sa1 = *(size_t*)u1;
+ size_t sa2 = *(size_t*)u2;
+ u1 += sizeof(size_t);
+ u2 += sizeof(size_t);
+ return arrayOrder(*(void* const*)u1, sa1, *(void* const*)u2, sa2, mt);
+ }
+ return orderJumpTable[mt->typeKind]((const void*)u1, (const void*)u2, mt);
+}
+
+static UA_Order
+notImplementedOrder(const void *p1, const void *p2, const UA_DataType *type) {
+ return UA_ORDER_EQ;
+}
+
+const
+UA_orderSignature orderJumpTable[UA_DATATYPEKINDS] = {
+ (UA_orderSignature)booleanOrder,
+ (UA_orderSignature)sByteOrder,
+ (UA_orderSignature)byteOrder,
+ (UA_orderSignature)int16Order,
+ (UA_orderSignature)uInt16Order,
+ (UA_orderSignature)int32Order,
+ (UA_orderSignature)uInt32Order,
+ (UA_orderSignature)int64Order,
+ (UA_orderSignature)uInt64Order,
+ (UA_orderSignature)floatOrder,
+ (UA_orderSignature)doubleOrder,
+ (UA_orderSignature)stringOrder,
+ (UA_orderSignature)int64Order, /* DateTime */
+ (UA_orderSignature)guidOrder,
+ (UA_orderSignature)stringOrder, /* ByteString */
+ (UA_orderSignature)stringOrder, /* XmlElement */
+ (UA_orderSignature)nodeIdOrder,
+ (UA_orderSignature)expandedNodeIdOrder,
+ (UA_orderSignature)uInt32Order, /* StatusCode */
+ (UA_orderSignature)qualifiedNameOrder,
+ (UA_orderSignature)localizedTextOrder,
+ (UA_orderSignature)extensionObjectOrder,
+ (UA_orderSignature)dataValueOrder,
+ (UA_orderSignature)variantOrder,
+ (UA_orderSignature)diagnosticInfoOrder,
+ notImplementedOrder, /* Decimal, not implemented */
+ (UA_orderSignature)uInt32Order, /* Enumeration */
+ (UA_orderSignature)structureOrder,
+ (UA_orderSignature)structureOrder, /* Struct with Optional Fields*/
+ (UA_orderSignature)unionOrder, /* Union*/
+ notImplementedOrder /* BitfieldCluster, not implemented */
+};
+
+UA_Order UA_order(const void *p1, const void *p2, const UA_DataType *type) {
+ return orderJumpTable[type->typeKind](p1, p2, type);
+}
+
+/******************/
/* Array Handling */
/******************/
@@ -8821,6 +6928,93 @@ UA_Array_copy(const void *src, size_t size,
return retval;
}
+UA_StatusCode
+UA_Array_resize(void **p, size_t *size, size_t newSize,
+ const UA_DataType *type) {
+ if(*size == newSize)
+ return UA_STATUSCODE_GOOD;
+
+ /* Empty array? */
+ if(newSize == 0) {
+ UA_Array_delete(*p, *size, type);
+ *p = UA_EMPTY_ARRAY_SENTINEL;
+ *size = 0;
+ return UA_STATUSCODE_GOOD;
+ }
+
+ /* Make a copy of the members that shall be removed. Realloc can fail during
+ * trimming. So we cannot clear the members already here. */
+ void *deleteMembers = NULL;
+ if(newSize < *size && !type->pointerFree) {
+ size_t deleteSize = *size - newSize;
+ deleteMembers = UA_malloc(deleteSize * type->memSize);
+ if(!deleteMembers)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ memcpy(deleteMembers, (void*)((uintptr_t)*p + (newSize * type->memSize)),
+ deleteSize * type->memSize); /* shallow copy */
+ }
+
+ void *oldP = *p;
+ if(oldP == UA_EMPTY_ARRAY_SENTINEL)
+ oldP = NULL;
+
+ /* Realloc */
+ void *newP = UA_realloc(oldP, newSize * type->memSize);
+ if(!newP) {
+ if(deleteMembers)
+ UA_free(deleteMembers);
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ }
+
+ /* Clear removed members or initialize the new ones. Note that deleteMembers
+ * depends on type->pointerFree. */
+ if(newSize > *size)
+ memset((void*)((uintptr_t)newP + (*size * type->memSize)), 0,
+ (newSize - *size) * type->memSize);
+ else if(deleteMembers)
+ UA_Array_delete(deleteMembers, *size - newSize, type);
+
+ /* Set the new array */
+ *p = newP;
+ *size = newSize;
+ return UA_STATUSCODE_GOOD;
+}
+
+UA_StatusCode
+UA_Array_append(void **p, size_t *size, void *newElem,
+ const UA_DataType *type) {
+ /* Resize the array */
+ size_t oldSize = *size;
+ UA_StatusCode res = UA_Array_resize(p, size, oldSize+1, type);
+ if(res != UA_STATUSCODE_GOOD)
+ return res;
+
+ /* Move the value */
+ memcpy((void*)((uintptr_t)*p + (oldSize * type->memSize)),
+ newElem, type->memSize);
+ UA_init(newElem, type);
+ return UA_STATUSCODE_GOOD;
+}
+
+UA_StatusCode UA_EXPORT
+UA_Array_appendCopy(void **p, size_t *size, const void *newElem,
+ const UA_DataType *type) {
+ char scratch[512];
+ if(type->memSize > 512)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ /* Copy the value */
+ UA_StatusCode res = UA_copy(newElem, (void*)scratch, type);
+ if(res != UA_STATUSCODE_GOOD)
+ return res;
+
+ /* Append */
+ res = UA_Array_append(p, size, (void*)scratch, type);
+ if(res != UA_STATUSCODE_GOOD)
+ UA_clear((void*)scratch, type);
+ return res;
+}
+
void
UA_Array_delete(void *p, size_t size, const UA_DataType *type) {
if(!type->pointerFree) {
@@ -8833,14 +7027,113 @@ UA_Array_delete(void *p, size_t size, const UA_DataType *type) {
UA_free((void*)((uintptr_t)p & ~(uintptr_t)UA_EMPTY_ARRAY_SENTINEL));
}
+#ifdef UA_ENABLE_TYPEDESCRIPTION
UA_Boolean
-UA_DataType_isNumeric(const UA_DataType *type) {
- /* All data types between UA_TYPES_BOOLEAN and UA_TYPES_DOUBLE are numeric */
- for(size_t i = UA_TYPES_BOOLEAN; i <= UA_TYPES_DOUBLE; ++i)
- if(&UA_TYPES[i] == type)
+UA_DataType_getStructMember(const UA_DataType *type, const char *memberName,
+ size_t *outOffset, const UA_DataType **outMemberType,
+ UA_Boolean *outIsArray) {
+ if(type->typeKind != UA_DATATYPEKIND_STRUCTURE &&
+ type->typeKind != UA_DATATYPEKIND_OPTSTRUCT)
+ return false;
+
+ size_t offset = 0;
+ for(size_t i = 0; i < type->membersSize; ++i) {
+ const UA_DataTypeMember *m = &type->members[i];
+ const UA_DataType *mt = m->memberType;
+ offset += m->padding;
+
+ if(strcmp(memberName, m->memberName) == 0) {
+ *outOffset = offset;
+ *outMemberType = mt;
+ *outIsArray = m->isArray;
return true;
+ }
+
+ if(!m->isOptional) {
+ if(!m->isArray) {
+ offset += mt->memSize;
+ } else {
+ offset += sizeof(size_t);
+ offset += sizeof(void*);
+ }
+ } else { /* field is optional */
+ if(!m->isArray) {
+ offset += sizeof(void *);
+ } else {
+ offset += sizeof(size_t);
+ offset += sizeof(void *);
+ }
+ }
+ }
+
return false;
}
+#endif
+
+UA_Boolean
+UA_DataType_isNumeric(const UA_DataType *type) {
+ switch(type->typeKind) {
+ case UA_DATATYPEKIND_SBYTE:
+ case UA_DATATYPEKIND_BYTE:
+ case UA_DATATYPEKIND_INT16:
+ case UA_DATATYPEKIND_UINT16:
+ case UA_DATATYPEKIND_INT32:
+ case UA_DATATYPEKIND_UINT32:
+ case UA_DATATYPEKIND_INT64:
+ case UA_DATATYPEKIND_UINT64:
+ case UA_DATATYPEKIND_FLOAT:
+ case UA_DATATYPEKIND_DOUBLE:
+ /* not implemented: UA_DATATYPEKIND_DECIMAL */
+ return true;
+ default:
+ return false;
+ }
+}
+
+UA_Int16
+UA_DataType_getPrecedence(const UA_DataType *type){
+ //Defined in Part 4 Table 123 "Data Precedence Rules"
+ switch(type->typeKind) {
+ case UA_DATATYPEKIND_DOUBLE:
+ return 1;
+ case UA_DATATYPEKIND_FLOAT:
+ return 2;
+ case UA_DATATYPEKIND_INT64:
+ return 3;
+ case UA_DATATYPEKIND_UINT64:
+ return 4;
+ case UA_DATATYPEKIND_INT32:
+ return 5;
+ case UA_DATATYPEKIND_UINT32:
+ return 6;
+ case UA_DATATYPEKIND_STATUSCODE:
+ return 7;
+ case UA_DATATYPEKIND_INT16:
+ return 8;
+ case UA_DATATYPEKIND_UINT16:
+ return 9;
+ case UA_DATATYPEKIND_SBYTE:
+ return 10;
+ case UA_DATATYPEKIND_BYTE:
+ return 11;
+ case UA_DATATYPEKIND_BOOLEAN:
+ return 12;
+ case UA_DATATYPEKIND_GUID:
+ return 13;
+ case UA_DATATYPEKIND_STRING:
+ return 14;
+ case UA_DATATYPEKIND_EXPANDEDNODEID:
+ return 15;
+ case UA_DATATYPEKIND_NODEID:
+ return 16;
+ case UA_DATATYPEKIND_LOCALIZEDTEXT:
+ return 17;
+ case UA_DATATYPEKIND_QUALIFIEDNAME:
+ return 18;
+ default:
+ return -1;
+ }
+}
/**********************/
/* Parse NumericRange */
@@ -8913,13 +7206,14 @@ UA_NumericRange_parse(UA_NumericRange *range, const UA_String str) {
if(retval == UA_STATUSCODE_GOOD && idx > 0) {
range->dimensions = dimensions;
range->dimensionsSize = idx;
- } else
+ } else {
UA_free(dimensions);
+ }
return retval;
}
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/src/ua_types_encoding_binary.c" ***********************************/
+/**** amalgamated original file "/src/ua_types_encoding_binary.c" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -8927,7 +7221,7 @@ UA_NumericRange_parse(UA_NumericRange *range, const UA_String str) {
*
* Copyright 2020 (c) Fraunhofer IOSB (Author: Andreas Ebner)
* Copyright 2020 (c) Grigory Friedman
- * Copyright 2014-2018 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
+ * Copyright 2014-2021 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
* Copyright 2014-2017 (c) Florian Palm
* Copyright 2014-2016 (c) Sten Grüner
* Copyright 2014 (c) Leon Urbas
@@ -8949,12 +7243,10 @@ UA_NumericRange_parse(UA_NumericRange *range, const UA_String str) {
* data types and generic functions that operate on all types and arrays. This
* requires the type description from a UA_DataType structure.
*
- * Encoding Context
- * ^^^^^^^^^^^^^^^^
- * If possible, the encoding context is stored in a thread-local variable to
- * speed up encoding. If thread-local variables are not supported, the context
- * is "looped through" every method call. The ``_``-macro accesses either the
- * thread-local or the "looped through" context . */
+ * Breaking a message up into chunks is integrated with the encoding. When the
+ * end of a buffer is reached, a callback is executed that sends the current
+ * buffer as a chunk and exchanges the encoding buffer "underneath" the ongoing
+ * encoding. This reduces the RAM requirements and unnecessary copying. */
/* Part 6 §5.1.5: Decoders shall support at least 100 nesting levels */
#define UA_ENCODING_MAX_RECURSION 100
@@ -9000,11 +7292,6 @@ extern const encodeBinarySignature encodeBinaryJumpTable[UA_DATATYPEKINDS];
extern const decodeBinarySignature decodeBinaryJumpTable[UA_DATATYPEKINDS];
extern const calcSizeBinarySignature calcSizeBinaryJumpTable[UA_DATATYPEKINDS];
-/* Breaking a message up into chunks is integrated with the encoding. When the
- * end of a buffer is reached, a callback is executed that sends the current
- * buffer as a chunk and exchanges the encoding buffer "underneath" the ongoing
- * encoding. This reduces the RAM requirements and unnecessary copying. */
-
/* Send the current chunk and replace the buffer */
static status exchangeBuffer(Ctx *ctx) {
if(!ctx->exchangeBufferCallback)
@@ -9018,10 +7305,11 @@ static status
encodeWithExchangeBuffer(const void *ptr, const UA_DataType *type, Ctx *ctx) {
u8 *oldpos = ctx->pos; /* Last known good position */
#ifndef NDEBUG
- /* Ensure that the buffer was not exchanged AND BADENCODINGLIMITSEXCEEDED
- * was returned. If that were the case, oldpos would be invalid. That means,
- * a type encoding must not return BADENCODINGLIMITSEXCEEDED after the
- * buffer could have been exchanged. */
+ /* We have to ensure that the buffer was not exchanged AND
+ * BADENCODINGLIMITSEXCEEDED was returned. If that were the case, oldpos
+ * would be invalid. That means, a type encoding must never return
+ * BADENCODINGLIMITSEXCEEDED once the buffer could have been exchanged. This
+ * is achieved by the use of encodeWithExchangeBuffer. */
const u8 *oldend = ctx->end;
(void)oldend; /* For compilers who don't understand NDEBUG... */
#endif
@@ -9030,8 +7318,7 @@ encodeWithExchangeBuffer(const void *ptr, const UA_DataType *type, Ctx *ctx) {
UA_assert(ctx->end == oldend);
ctx->pos = oldpos; /* Set to the last known good position and exchange */
ret = exchangeBuffer(ctx);
- if(ret != UA_STATUSCODE_GOOD)
- return ret;
+ UA_CHECK_STATUS(ret, return ret);
ret = encodeBinaryJumpTable[type->typeKind](ptr, type, ctx);
}
return ret;
@@ -9097,16 +7384,14 @@ UA_decode64(const u8 buf[8], u64 *v) {
/* Note that sizeof(bool) != 1 on some platforms. Overlayable integer encoding
* is disabled in those cases. */
ENCODE_BINARY(Boolean) {
- if(ctx->pos + 1 > ctx->end)
- return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED;
+ UA_CHECK(ctx->pos + 1 <= ctx->end, return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
*ctx->pos = *(const u8*)src;
++ctx->pos;
return UA_STATUSCODE_GOOD;
}
DECODE_BINARY(Boolean) {
- if(ctx->pos + 1 > ctx->end)
- return UA_STATUSCODE_BADDECODINGERROR;
+ UA_CHECK(ctx->pos + 1 <= ctx->end, return UA_STATUSCODE_BADDECODINGERROR);
*dst = (*ctx->pos > 0) ? true : false;
++ctx->pos;
return UA_STATUSCODE_GOOD;
@@ -9114,16 +7399,16 @@ DECODE_BINARY(Boolean) {
/* Byte */
ENCODE_BINARY(Byte) {
- if(ctx->pos + sizeof(u8) > ctx->end)
- return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED;
+ UA_CHECK(ctx->pos + sizeof(u8) <= ctx->end,
+ return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
*ctx->pos = *(const u8*)src;
++ctx->pos;
return UA_STATUSCODE_GOOD;
}
DECODE_BINARY(Byte) {
- if(ctx->pos + sizeof(u8) > ctx->end)
- return UA_STATUSCODE_BADDECODINGERROR;
+ UA_CHECK(ctx->pos + sizeof(u8) <= ctx->end,
+ return UA_STATUSCODE_BADDECODINGERROR);
*dst = *ctx->pos;
++ctx->pos;
return UA_STATUSCODE_GOOD;
@@ -9131,8 +7416,8 @@ DECODE_BINARY(Byte) {
/* UInt16 */
ENCODE_BINARY(UInt16) {
- if(ctx->pos + sizeof(u16) > ctx->end)
- return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED;
+ UA_CHECK(ctx->pos + sizeof(u16) <= ctx->end,
+ return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
#if UA_BINARY_OVERLAYABLE_INTEGER
memcpy(ctx->pos, src, sizeof(u16));
#else
@@ -9143,8 +7428,8 @@ ENCODE_BINARY(UInt16) {
}
DECODE_BINARY(UInt16) {
- if(ctx->pos + sizeof(u16) > ctx->end)
- return UA_STATUSCODE_BADDECODINGERROR;
+ UA_CHECK(ctx->pos + sizeof(u16) <= ctx->end,
+ return UA_STATUSCODE_BADDECODINGERROR);
#if UA_BINARY_OVERLAYABLE_INTEGER
memcpy(dst, ctx->pos, sizeof(u16));
#else
@@ -9156,8 +7441,8 @@ DECODE_BINARY(UInt16) {
/* UInt32 */
ENCODE_BINARY(UInt32) {
- if(ctx->pos + sizeof(u32) > ctx->end)
- return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED;
+ UA_CHECK(ctx->pos + sizeof(u32) <= ctx->end,
+ return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
#if UA_BINARY_OVERLAYABLE_INTEGER
memcpy(ctx->pos, src, sizeof(u32));
#else
@@ -9168,8 +7453,8 @@ ENCODE_BINARY(UInt32) {
}
DECODE_BINARY(UInt32) {
- if(ctx->pos + sizeof(u32) > ctx->end)
- return UA_STATUSCODE_BADDECODINGERROR;
+ UA_CHECK(ctx->pos + sizeof(u32) <= ctx->end,
+ return UA_STATUSCODE_BADDECODINGERROR);
#if UA_BINARY_OVERLAYABLE_INTEGER
memcpy(dst, ctx->pos, sizeof(u32));
#else
@@ -9181,8 +7466,8 @@ DECODE_BINARY(UInt32) {
/* UInt64 */
ENCODE_BINARY(UInt64) {
- if(ctx->pos + sizeof(u64) > ctx->end)
- return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED;
+ UA_CHECK(ctx->pos + sizeof(u64) <= ctx->end,
+ return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
#if UA_BINARY_OVERLAYABLE_INTEGER
memcpy(ctx->pos, src, sizeof(u64));
#else
@@ -9193,8 +7478,8 @@ ENCODE_BINARY(UInt64) {
}
DECODE_BINARY(UInt64) {
- if(ctx->pos + sizeof(u64) > ctx->end)
- return UA_STATUSCODE_BADDECODINGERROR;
+ UA_CHECK(ctx->pos + sizeof(u64) <= ctx->end,
+ return UA_STATUSCODE_BADDECODINGERROR);
#if UA_BINARY_OVERLAYABLE_INTEGER
memcpy(dst, ctx->pos, sizeof(u64));
#else
@@ -9244,7 +7529,7 @@ static long double
unpack754(uint64_t i, unsigned bits, unsigned expbits) {
unsigned significandbits = bits - expbits - 1;
long double result = (long double)(i&(uint64_t)((1LL<<significandbits)-1));
- result /= (1LL<<significandbits);
+ result /= (long double)(1LL<<significandbits);
result += 1.0f;
unsigned bias = (unsigned)(1<<(expbits-1)) - 1;
long long shift = (long long)((i>>significandbits) & (uint64_t)((1LL<<expbits)-1)) - bias;
@@ -9306,8 +7591,7 @@ ENCODE_BINARY(Double) {
DECODE_BINARY(Double) {
u64 decoded;
status ret = DECODE_DIRECT(&decoded, UInt64);
- if(ret != UA_STATUSCODE_GOOD)
- return ret;
+ UA_CHECK_STATUS(ret, return ret);
if(decoded == 0) *dst = 0.0;
else if(decoded == DOUBLE_NEG_ZERO) *dst = -0.0;
else if(decoded == DOUBLE_INF) *dst = INFINITY;
@@ -9333,8 +7617,8 @@ Array_encodeBinaryOverlayable(uintptr_t ptr, size_t memSize, Ctx *ctx) {
ctx->pos += possible;
ptr += possible;
status ret = exchangeBuffer(ctx);
- if(ret != UA_STATUSCODE_GOOD)
- return ret;
+ UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
+ UA_CHECK_STATUS(ret, return ret);
memSize -= possible;
}
@@ -9351,10 +7635,9 @@ Array_encodeBinaryComplex(uintptr_t ptr, size_t length,
for(size_t i = 0; i < length; ++i) {
status ret = encodeWithExchangeBuffer((const void*)ptr, type, ctx);
ptr += type->memSize;
- if(ret != UA_STATUSCODE_GOOD)
- return ret; /* Unrecoverable fail */
+ UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
+ UA_CHECK_STATUS(ret, return ret); /* Unrecoverable fail */
}
-
return UA_STATUSCODE_GOOD;
}
@@ -9372,14 +7655,15 @@ Array_encodeBinary(const void *src, size_t length, const UA_DataType *type, Ctx
/* Encode the array length */
status ret = encodeWithExchangeBuffer(&signed_length, &UA_TYPES[UA_TYPES_INT32], ctx);
UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
- if(ret != UA_STATUSCODE_GOOD || length == 0)
- return ret;
+ UA_CHECK_STATUS(ret, return ret);
/* Encode the content */
- if(type->overlayable)
- ret = Array_encodeBinaryOverlayable((uintptr_t)src, length * type->memSize, ctx);
- else
- ret = Array_encodeBinaryComplex((uintptr_t)src, length, type, ctx);
+ if(length > 0) {
+ if(type->overlayable)
+ ret = Array_encodeBinaryOverlayable((uintptr_t)src, length * type->memSize, ctx);
+ else
+ ret = Array_encodeBinaryComplex((uintptr_t)src, length, type, ctx);
+ }
UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
return ret;
}
@@ -9390,8 +7674,7 @@ Array_decodeBinary(void *UA_RESTRICT *UA_RESTRICT dst, size_t *out_length,
/* Decode the length */
i32 signed_length;
status ret = DECODE_DIRECT(&signed_length, UInt32); /* Int32 */
- if(ret != UA_STATUSCODE_GOOD)
- return ret;
+ UA_CHECK_STATUS(ret, return ret);
/* Return early for empty arrays */
if(signed_length <= 0) {
@@ -9407,21 +7690,17 @@ Array_decodeBinary(void *UA_RESTRICT *UA_RESTRICT dst, size_t *out_length,
* is too small for the array length. This prevents the allocation of very
* long arrays for bogus messages.*/
size_t length = (size_t)signed_length;
- if(ctx->pos + ((type->memSize * length) / 32) > ctx->end)
- return UA_STATUSCODE_BADDECODINGERROR;
+ UA_CHECK(ctx->pos + ((type->memSize * length) / 32) <= ctx->end,
+ return UA_STATUSCODE_BADDECODINGERROR);
/* Allocate memory */
*dst = UA_calloc(length, type->memSize);
- if(!*dst)
- return UA_STATUSCODE_BADOUTOFMEMORY;
+ UA_CHECK_MEM(*dst, return UA_STATUSCODE_BADOUTOFMEMORY);
if(type->overlayable) {
/* memcpy overlayable array */
- if(ctx->end < ctx->pos + (type->memSize * length)) {
- UA_free(*dst);
- *dst = NULL;
- return UA_STATUSCODE_BADDECODINGERROR;
- }
+ UA_CHECK(ctx->pos + (type->memSize * length) <= ctx->end,
+ UA_free(*dst); *dst = NULL; return UA_STATUSCODE_BADDECODINGERROR);
memcpy(*dst, ctx->pos, type->memSize * length);
ctx->pos += type->memSize * length;
} else {
@@ -9429,12 +7708,8 @@ Array_decodeBinary(void *UA_RESTRICT *UA_RESTRICT dst, size_t *out_length,
uintptr_t ptr = (uintptr_t)*dst;
for(size_t i = 0; i < length; ++i) {
ret = decodeBinaryJumpTable[type->typeKind]((void*)ptr, type, ctx);
- if(ret != UA_STATUSCODE_GOOD) {
- /* +1 because last element is also already initialized */
- UA_Array_delete(*dst, i+1, type);
- *dst = NULL;
- return ret;
- }
+ UA_CHECK_STATUS(ret, /* +1 because last element is also already initialized */
+ UA_Array_delete(*dst, i+1, type); *dst = NULL; return ret);
ptr += type->memSize;
}
}
@@ -9460,8 +7735,8 @@ ENCODE_BINARY(Guid) {
ret |= ENCODE_DIRECT(&src->data1, UInt32);
ret |= ENCODE_DIRECT(&src->data2, UInt16);
ret |= ENCODE_DIRECT(&src->data3, UInt16);
- if(ctx->pos + (8*sizeof(u8)) > ctx->end)
- return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED;
+ UA_CHECK(ctx->pos + (8*sizeof(u8)) <= ctx->end,
+ return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
memcpy(ctx->pos, src->data4, 8*sizeof(u8));
ctx->pos += 8;
return ret;
@@ -9472,8 +7747,8 @@ DECODE_BINARY(Guid) {
ret |= DECODE_DIRECT(&dst->data1, UInt32);
ret |= DECODE_DIRECT(&dst->data2, UInt16);
ret |= DECODE_DIRECT(&dst->data3, UInt16);
- if(ctx->pos + (8*sizeof(u8)) > ctx->end)
- return UA_STATUSCODE_BADDECODINGERROR;
+ UA_CHECK(ctx->pos + (8*sizeof(u8)) <= ctx->end,
+ return UA_STATUSCODE_BADDECODINGERROR);
memcpy(dst->data4, ctx->pos, 8*sizeof(u8));
ctx->pos += 8;
return ret;
@@ -9516,8 +7791,8 @@ NodeId_encodeBinaryWithEncodingMask(UA_NodeId const *src, u8 encoding, Ctx *ctx)
encoding |= (u8)UA_NODEIDTYPE_STRING;
ret |= ENCODE_DIRECT(&encoding, Byte);
ret |= ENCODE_DIRECT(&src->namespaceIndex, UInt16);
- if(ret != UA_STATUSCODE_GOOD)
- return ret;
+ UA_CHECK_STATUS(ret, return ret);
+ /* Can exchange the buffer */
ret = ENCODE_DIRECT(&src->identifier.string, String);
UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
break;
@@ -9531,8 +7806,8 @@ NodeId_encodeBinaryWithEncodingMask(UA_NodeId const *src, u8 encoding, Ctx *ctx)
encoding |= (u8)UA_NODEIDTYPE_BYTESTRING;
ret |= ENCODE_DIRECT(&encoding, Byte);
ret |= ENCODE_DIRECT(&src->namespaceIndex, UInt16);
- if(ret != UA_STATUSCODE_GOOD)
- return ret;
+ UA_CHECK_STATUS(ret, return ret);
+ /* Can exchange the buffer */
ret = ENCODE_DIRECT(&src->identifier.byteString, String); /* ByteString */
UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
break;
@@ -9552,8 +7827,7 @@ DECODE_BINARY(NodeId) {
/* Decode the encoding bitfield */
status ret = DECODE_DIRECT(&encodingByte, Byte);
- if(ret != UA_STATUSCODE_GOOD)
- return ret;
+ UA_CHECK_STATUS(ret, return ret);
/* Filter out the bits used only for ExpandedNodeIds */
encodingByte &= (u8)~(u8)(UA_EXPANDEDNODEID_SERVERINDEX_FLAG |
@@ -9610,17 +7884,17 @@ ENCODE_BINARY(ExpandedNodeId) {
if(src->serverIndex > 0)
encoding |= UA_EXPANDEDNODEID_SERVERINDEX_FLAG;
- /* Encode the NodeId */
+ /* Encode the NodeId. Can exchange the buffer. */
status ret = NodeId_encodeBinaryWithEncodingMask(&src->nodeId, encoding, ctx);
- if(ret != UA_STATUSCODE_GOOD)
- return ret;
+ UA_CHECK_STATUS(ret, return ret);
- /* Encode the namespace. */
+ /* Encode the namespace. Internally uses encodeWithExchangeBuffer
+ * everywhere. So it will never return
+ * UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED. */
if((void*)src->namespaceUri.data > UA_EMPTY_ARRAY_SENTINEL) {
ret = ENCODE_DIRECT(&src->namespaceUri, String);
UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
- if(ret != UA_STATUSCODE_GOOD)
- return ret;
+ UA_CHECK_STATUS(ret, return ret);
}
/* Encode the serverIndex */
@@ -9632,8 +7906,7 @@ ENCODE_BINARY(ExpandedNodeId) {
DECODE_BINARY(ExpandedNodeId) {
/* Decode the encoding mask */
- if(ctx->pos >= ctx->end)
- return UA_STATUSCODE_BADDECODINGERROR;
+ UA_CHECK(ctx->pos + 1 <= ctx->end, return UA_STATUSCODE_BADDECODINGERROR);
u8 encoding = *ctx->pos;
/* Decode the NodeId */
@@ -9654,8 +7927,8 @@ DECODE_BINARY(ExpandedNodeId) {
/* QualifiedName */
ENCODE_BINARY(QualifiedName) {
status ret = ENCODE_DIRECT(&src->namespaceIndex, UInt16);
- if(ret != UA_STATUSCODE_GOOD)
- return ret;
+ /* Must check here so we can exchange the buffer in the string encoding */
+ UA_CHECK_STATUS(ret, return ret);
ret |= ENCODE_DIRECT(&src->name, String);
return ret;
}
@@ -9680,8 +7953,8 @@ ENCODE_BINARY(LocalizedText) {
/* Encode the encoding byte */
status ret = ENCODE_DIRECT(&encoding, Byte);
- if(ret != UA_STATUSCODE_GOOD)
- return ret;
+ /* Must check here so we can exchange the buffer in the string encoding */
+ UA_CHECK_STATUS(ret, return ret);
/* Encode the strings */
if(encoding & UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_LOCALE)
@@ -9709,23 +7982,21 @@ DECODE_BINARY(LocalizedText) {
* possible to reuse UA_findDataType */
static const UA_DataType *
UA_findDataTypeByBinaryInternal(const UA_NodeId *typeId, Ctx *ctx) {
- /* We only store a numeric identifier for the encoding nodeid of data types */
- if(typeId->identifierType != UA_NODEIDTYPE_NUMERIC)
- return NULL;
-
- /* Always look in built-in types first
- * (may contain data types from all namespaces) */
- for(size_t i = 0; i < UA_TYPES_COUNT; ++i) {
- if(UA_TYPES[i].binaryEncodingId == typeId->identifier.numeric &&
- UA_TYPES[i].typeId.namespaceIndex == typeId->namespaceIndex)
- return &UA_TYPES[i];
+ /* Always look in the built-in types first. Assume that only numeric
+ * identifiers are used for the builtin types. (They may contain data types
+ * from all namespaces though.) */
+ if(typeId->identifierType == UA_NODEIDTYPE_NUMERIC) {
+ for(size_t i = 0; i < UA_TYPES_COUNT; ++i) {
+ if(UA_TYPES[i].binaryEncodingId.identifier.numeric == typeId->identifier.numeric &&
+ UA_TYPES[i].binaryEncodingId.namespaceIndex == typeId->namespaceIndex)
+ return &UA_TYPES[i];
+ }
}
const UA_DataTypeArray *customTypes = ctx->customTypes;
while(customTypes) {
for(size_t i = 0; i < customTypes->typesSize; ++i) {
- if(customTypes->types[i].binaryEncodingId == typeId->identifier.numeric &&
- customTypes->types[i].typeId.namespaceIndex == typeId->namespaceIndex)
+ if(UA_NodeId_equal(typeId, &customTypes->types[i].binaryEncodingId))
return &customTypes->types[i];
}
customTypes = customTypes->next;
@@ -9747,18 +8018,19 @@ ENCODE_BINARY(ExtensionObject) {
/* No content or already encoded content. */
if(encoding <= UA_EXTENSIONOBJECT_ENCODED_XML) {
+ /* Can exchange the buffer */
status ret = ENCODE_DIRECT(&src->content.encoded.typeId, NodeId);
- if(ret != UA_STATUSCODE_GOOD)
- return ret;
+ UA_CHECK_STATUS(ret, return ret);
ret = encodeWithExchangeBuffer(&encoding, &UA_TYPES[UA_TYPES_BYTE], ctx);
- if(ret != UA_STATUSCODE_GOOD)
- return ret;
+ UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
+ UA_CHECK_STATUS(ret, return ret);
switch(src->encoding) {
case UA_EXTENSIONOBJECT_ENCODED_NOBODY:
break;
case UA_EXTENSIONOBJECT_ENCODED_BYTESTRING:
case UA_EXTENSIONOBJECT_ENCODED_XML:
- ret = ENCODE_DIRECT(&src->content.encoded.body, String); /* ByteString */
+ /* ByteString in disguise. Array encoding can exchange the buffer */
+ ret = ENCODE_DIRECT(&src->content.encoded.body, String);
break;
default:
ret = UA_STATUSCODE_BADINTERNALERROR;
@@ -9771,37 +8043,35 @@ ENCODE_BINARY(ExtensionObject) {
if(!src->content.decoded.type || !src->content.decoded.data)
return UA_STATUSCODE_BADENCODINGERROR;
- /* Write the NodeId for the binary encoded type. The NodeId is always
- * numeric, so no buffer replacement is taking place. */
- UA_NodeId typeId = src->content.decoded.type->typeId;
- if(typeId.identifierType != UA_NODEIDTYPE_NUMERIC)
- return UA_STATUSCODE_BADENCODINGERROR;
- typeId.identifier.numeric = src->content.decoded.type->binaryEncodingId;
- status ret = ENCODE_DIRECT(&typeId, NodeId);
- UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
- if(ret != UA_STATUSCODE_GOOD)
- return ret;
+ /* Write the NodeId for the binary encoded type. This could perform a buffer
+ * exchange, but can also return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED. */
+ status ret = ENCODE_DIRECT(&src->content.decoded.type->binaryEncodingId, NodeId);
+ UA_CHECK_STATUS(ret, return ret);
/* Encode the encoding byte */
encoding = UA_EXTENSIONOBJECT_ENCODED_BYTESTRING;
- ret |= ENCODE_DIRECT(&encoding, Byte);
+ ret = encodeWithExchangeBuffer(&encoding, &UA_TYPES[UA_TYPES_BYTE], ctx);
+ UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
+ UA_CHECK_STATUS(ret, return ret);
/* Encode the content length */
const UA_DataType *contentType = src->content.decoded.type;
size_t len = UA_calcSizeBinary(src->content.decoded.data, contentType);
- if(len > UA_INT32_MAX)
- return UA_STATUSCODE_BADENCODINGERROR;
+ UA_CHECK(len <= UA_INT32_MAX, return UA_STATUSCODE_BADENCODINGERROR);
i32 signed_len = (i32)len;
- ret |= ENCODE_DIRECT(&signed_len, UInt32); /* Int32 */
- if(ret != UA_STATUSCODE_GOOD)
- return ret;
+ ret = encodeWithExchangeBuffer(&signed_len, &UA_TYPES[UA_TYPES_INT32], ctx);
+ UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
+ UA_CHECK_STATUS(ret, return ret);
/* Encode the content */
- return encodeWithExchangeBuffer(src->content.decoded.data, contentType, ctx);
+ ret = encodeWithExchangeBuffer(src->content.decoded.data, contentType, ctx);
+ UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
+ return ret;
}
static status
-ExtensionObject_decodeBinaryContent(UA_ExtensionObject *dst, const UA_NodeId *typeId, Ctx *ctx) {
+ExtensionObject_decodeBinaryContent(UA_ExtensionObject *dst, const UA_NodeId *typeId,
+ Ctx *ctx) {
/* Lookup the datatype */
const UA_DataType *type = UA_findDataTypeByBinaryInternal(typeId, ctx);
@@ -9814,8 +8084,7 @@ ExtensionObject_decodeBinaryContent(UA_ExtensionObject *dst, const UA_NodeId *ty
/* Allocate memory */
dst->content.decoded.data = UA_new(type);
- if(!dst->content.decoded.data)
- return UA_STATUSCODE_BADOUTOFMEMORY;
+ UA_CHECK_MEM(dst->content.decoded.data, return UA_STATUSCODE_BADOUTOFMEMORY);
/* Jump over the length field (TODO: check if the decoded length matches) */
ctx->pos += 4;
@@ -9828,24 +8097,18 @@ ExtensionObject_decodeBinaryContent(UA_ExtensionObject *dst, const UA_NodeId *ty
DECODE_BINARY(ExtensionObject) {
u8 encoding = 0;
- UA_NodeId binTypeId; /* Can contain a string nodeid. But no corresponding
- * type is then found in open62541. We only store
- * numerical nodeids of the binary encoding identifier.
- * The extenionobject will be decoded to contain a
- * binary blob. */
+ UA_NodeId binTypeId;
UA_NodeId_init(&binTypeId);
+
status ret = UA_STATUSCODE_GOOD;
ret |= DECODE_DIRECT(&binTypeId, NodeId);
ret |= DECODE_DIRECT(&encoding, Byte);
- if(ret != UA_STATUSCODE_GOOD) {
- UA_NodeId_clear(&binTypeId);
- return ret;
- }
+ UA_CHECK_STATUS(ret, UA_NodeId_clear(&binTypeId); return ret);
switch(encoding) {
case UA_EXTENSIONOBJECT_ENCODED_BYTESTRING:
ret = ExtensionObject_decodeBinaryContent(dst, &binTypeId, ctx);
- UA_NodeId_deleteMembers(&binTypeId);
+ UA_NodeId_clear(&binTypeId);
break;
case UA_EXTENSIONOBJECT_ENCODED_NOBODY:
dst->encoding = (UA_ExtensionObjectEncoding)encoding;
@@ -9856,8 +8119,7 @@ DECODE_BINARY(ExtensionObject) {
dst->encoding = (UA_ExtensionObjectEncoding)encoding;
dst->content.encoded.typeId = binTypeId; /* move to dst */
ret = DECODE_DIRECT(&dst->content.encoded.body, String); /* ByteString */
- if(ret != UA_STATUSCODE_GOOD)
- UA_NodeId_clear(&dst->content.encoded.typeId);
+ UA_CHECK_STATUS(ret, UA_NodeId_clear(&dst->content.encoded.typeId));
break;
default:
UA_NodeId_clear(&binTypeId);
@@ -9878,13 +8140,11 @@ Variant_encodeBinaryWrapExtensionObject(const UA_Variant *src,
/* Encode the array length if required */
status ret = UA_STATUSCODE_GOOD;
if(isArray) {
- if(src->arrayLength > UA_INT32_MAX)
- return UA_STATUSCODE_BADENCODINGERROR;
+ UA_CHECK(src->arrayLength <= UA_INT32_MAX, return UA_STATUSCODE_BADENCODINGERROR);
length = src->arrayLength;
i32 encodedLength = (i32)src->arrayLength;
ret = ENCODE_DIRECT(&encodedLength, UInt32); /* Int32 */
- if(ret != UA_STATUSCODE_GOOD)
- return ret;
+ UA_CHECK_STATUS(ret, return ret);
}
/* Set up the ExtensionObject */
@@ -9899,6 +8159,7 @@ Variant_encodeBinaryWrapExtensionObject(const UA_Variant *src,
for(size_t i = 0; i < length && ret == UA_STATUSCODE_GOOD; ++i) {
eo.content.decoded.data = (void*)ptr;
ret = encodeWithExchangeBuffer(&eo, &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], ctx);
+ UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
ptr += memSize;
}
return ret;
@@ -9937,17 +8198,21 @@ ENCODE_BINARY(Variant) {
/* Encode the encoding byte */
status ret = ENCODE_DIRECT(&encoding, Byte);
- if(ret != UA_STATUSCODE_GOOD)
- return ret;
+ UA_CHECK_STATUS(ret, return ret);
- /* Encode the content */
- if(!isBuiltin && !isEnum)
+ /* Encode the content. This can exchange the buffer. */
+ if(!isBuiltin && !isEnum) {
+ /* This could return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED. But we
+ * have not exchanged the buffer so far. */
ret = Variant_encodeBinaryWrapExtensionObject(src, isArray, ctx);
- else if(!isArray)
+ } else if(!isArray) {
ret = encodeWithExchangeBuffer(src->data, src->type, ctx);
- else
+ UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
+ } else {
ret = Array_encodeBinary(src->data, src->arrayLength, src->type, ctx);
- UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
+ UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
+ }
+ UA_CHECK_STATUS(ret, return ret);
/* Encode the array dimensions */
if(hasDimensions && ret == UA_STATUSCODE_GOOD)
@@ -9967,16 +8232,12 @@ Variant_decodeBinaryUnwrapExtensionObject(UA_Variant *dst, Ctx *ctx) {
UA_NodeId typeId;
UA_NodeId_init(&typeId);
status ret = DECODE_DIRECT(&typeId, NodeId);
- if(ret != UA_STATUSCODE_GOOD)
- return ret;
+ UA_CHECK_STATUS(ret, return ret);
/* Decode the EncodingByte */
u8 encoding;
ret = DECODE_DIRECT(&encoding, Byte);
- if(ret != UA_STATUSCODE_GOOD) {
- UA_NodeId_clear(&typeId);
- return ret;
- }
+ UA_CHECK_STATUS(ret, UA_NodeId_clear(&typeId); return ret);
/* Search for the datatype. Default to ExtensionObject. */
if(encoding == UA_EXTENSIONOBJECT_ENCODED_BYTESTRING &&
@@ -9987,13 +8248,12 @@ Variant_decodeBinaryUnwrapExtensionObject(UA_Variant *dst, Ctx *ctx) {
/* Reset and decode as ExtensionObject */
dst->type = &UA_TYPES[UA_TYPES_EXTENSIONOBJECT];
ctx->pos = old_pos;
- UA_NodeId_clear(&typeId);
}
+ UA_NodeId_clear(&typeId);
/* Allocate memory */
dst->data = UA_new(dst->type);
- if(!dst->data)
- return UA_STATUSCODE_BADOUTOFMEMORY;
+ UA_CHECK_MEM(dst->data, return UA_STATUSCODE_BADOUTOFMEMORY);
/* Decode the content */
return decodeBinaryJumpTable[dst->type->typeKind](dst->data, dst->type, ctx);
@@ -10004,8 +8264,7 @@ DECODE_BINARY(Variant) {
/* Decode the encoding byte */
u8 encodingByte;
status ret = DECODE_DIRECT(&encodingByte, Byte);
- if(ret != UA_STATUSCODE_GOOD)
- return ret;
+ UA_CHECK_STATUS(ret, return ret);
/* Return early for an empty variant (was already _inited) */
if(encodingByte == 0)
@@ -10019,17 +8278,15 @@ DECODE_BINARY(Variant) {
* for types up to DiagnsticInfo equals to the index in the encoding
* byte. */
size_t typeKind = (size_t)((encodingByte & (u8)UA_VARIANT_ENCODINGMASKTYPE_TYPEID_MASK) - 1);
- if(typeKind > UA_DATATYPEKIND_DIAGNOSTICINFO)
- return UA_STATUSCODE_BADDECODINGERROR;
+ UA_CHECK(typeKind <= UA_DATATYPEKIND_DIAGNOSTICINFO, return UA_STATUSCODE_BADDECODINGERROR);
/* A variant cannot contain a variant. But it can contain an array of
* variants */
- if(typeKind == UA_DATATYPEKIND_VARIANT && !isArray)
- return UA_STATUSCODE_BADDECODINGERROR;
+ UA_CHECK(typeKind != UA_DATATYPEKIND_VARIANT || isArray,
+ return UA_STATUSCODE_BADDECODINGERROR);
/* Check the recursion limit */
- if(ctx->depth > UA_ENCODING_MAX_RECURSION)
- return UA_STATUSCODE_BADENCODINGERROR;
+ UA_CHECK(ctx->depth <= UA_ENCODING_MAX_RECURSION, return UA_STATUSCODE_BADENCODINGERROR);
ctx->depth++;
/* Decode the content */
@@ -10038,10 +8295,7 @@ DECODE_BINARY(Variant) {
ret = Array_decodeBinary(&dst->data, &dst->arrayLength, dst->type, ctx);
} else if(typeKind != UA_DATATYPEKIND_EXTENSIONOBJECT) {
dst->data = UA_new(dst->type);
- if(!dst->data) {
- ctx->depth--;
- return UA_STATUSCODE_BADOUTOFMEMORY;
- }
+ UA_CHECK_MEM(dst->data, ctx->depth--; return UA_STATUSCODE_BADOUTOFMEMORY);
ret = decodeBinaryJumpTable[typeKind](dst->data, dst->type, ctx);
} else {
ret = Variant_decodeBinaryUnwrapExtensionObject(dst, ctx);
@@ -10068,8 +8322,7 @@ ENCODE_BINARY(DataValue) {
/* Encode the encoding byte */
status ret = ENCODE_DIRECT(&encodingMask, Byte);
- if(ret != UA_STATUSCODE_GOOD)
- return ret;
+ UA_CHECK_STATUS(ret, return ret);
/* Encode the variant. */
if(src->hasValue) {
@@ -10098,12 +8351,10 @@ DECODE_BINARY(DataValue) {
/* Decode the encoding mask */
u8 encodingMask;
status ret = DECODE_DIRECT(&encodingMask, Byte);
- if(ret != UA_STATUSCODE_GOOD)
- return ret;
+ UA_CHECK_STATUS(ret, return ret);
/* Check the recursion limit */
- if(ctx->depth > UA_ENCODING_MAX_RECURSION)
- return UA_STATUSCODE_BADENCODINGERROR;
+ UA_CHECK(ctx->depth <= UA_ENCODING_MAX_RECURSION, return UA_STATUSCODE_BADENCODINGERROR);
ctx->depth++;
/* Decode the content */
@@ -10137,7 +8388,6 @@ DECODE_BINARY(DataValue) {
}
ctx->depth--;
-
return ret;
}
@@ -10149,8 +8399,9 @@ ENCODE_BINARY(DiagnosticInfo) {
encodingMask |= (u8)(src->hasLocalizedText << 2u);
encodingMask |= (u8)(src->hasLocale << 3u);
encodingMask |= (u8)(src->hasAdditionalInfo << 4u);
- encodingMask |= (u8)(src->hasInnerDiagnosticInfo << 5u);
-
+ encodingMask |= (u8)(src->hasInnerStatusCode << 5u);
+ encodingMask |= (u8)(src->hasInnerDiagnosticInfo << 6u);
+
/* Encode the numeric content */
status ret = ENCODE_DIRECT(&encodingMask, Byte);
if(src->hasSymbolicId)
@@ -10164,24 +8415,26 @@ ENCODE_BINARY(DiagnosticInfo) {
if(ret != UA_STATUSCODE_GOOD)
return ret;
- /* Encode the additional info */
+ /* Encode the additional info. Can exchange the buffer. */
if(src->hasAdditionalInfo) {
ret = ENCODE_DIRECT(&src->additionalInfo, String);
- if(ret != UA_STATUSCODE_GOOD)
- return ret;
+ UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
+ UA_CHECK_STATUS(ret, return ret);
}
/* Encode the inner status code */
if(src->hasInnerStatusCode) {
ret = encodeWithExchangeBuffer(&src->innerStatusCode, &UA_TYPES[UA_TYPES_UINT32], ctx);
- if(ret != UA_STATUSCODE_GOOD)
- return ret;
+ UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
+ UA_CHECK_STATUS(ret, return ret);
}
/* Encode the inner diagnostic info */
- if(src->hasInnerDiagnosticInfo)
+ if(src->hasInnerDiagnosticInfo) {
ret = encodeWithExchangeBuffer(src->innerDiagnosticInfo,
&UA_TYPES[UA_TYPES_DIAGNOSTICINFO], ctx);
+ UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
+ }
return ret;
}
@@ -10190,8 +8443,7 @@ DECODE_BINARY(DiagnosticInfo) {
/* Decode the encoding mask */
u8 encodingMask;
status ret = DECODE_DIRECT(&encodingMask, Byte);
- if(ret != UA_STATUSCODE_GOOD)
- return ret;
+ UA_CHECK_STATUS(ret, return ret);
/* Decode the content */
if(encodingMask & 0x01u) {
@@ -10222,13 +8474,12 @@ DECODE_BINARY(DiagnosticInfo) {
/* innerDiagnosticInfo is allocated on the heap */
dst->innerDiagnosticInfo = (UA_DiagnosticInfo*)
UA_calloc(1, sizeof(UA_DiagnosticInfo));
- if(!dst->innerDiagnosticInfo)
- return UA_STATUSCODE_BADOUTOFMEMORY;
+ UA_CHECK_MEM(dst->innerDiagnosticInfo, return UA_STATUSCODE_BADOUTOFMEMORY);
dst->hasInnerDiagnosticInfo = true;
/* Check the recursion limit */
- if(ctx->depth > UA_ENCODING_MAX_RECURSION)
- return UA_STATUSCODE_BADENCODINGERROR;
+ UA_CHECK(ctx->depth <= UA_ENCODING_MAX_RECURSION,
+ return UA_STATUSCODE_BADENCODINGERROR);
ctx->depth++;
ret |= DECODE_DIRECT(dst->innerDiagnosticInfo, DiagnosticInfo);
@@ -10237,20 +8488,23 @@ DECODE_BINARY(DiagnosticInfo) {
return ret;
}
+/********************/
+/* Structured Types */
+/********************/
+
static status
encodeBinaryStruct(const void *src, const UA_DataType *type, Ctx *ctx) {
/* Check the recursion limit */
- if(ctx->depth > UA_ENCODING_MAX_RECURSION)
- return UA_STATUSCODE_BADENCODINGERROR;
+ UA_CHECK(ctx->depth <= UA_ENCODING_MAX_RECURSION,
+ return UA_STATUSCODE_BADENCODINGERROR);
ctx->depth++;
/* Loop over members */
uintptr_t ptr = (uintptr_t)src;
status ret = UA_STATUSCODE_GOOD;
- const UA_DataType *typelists[2] = { UA_TYPES, &type[-type->typeIndex] };
for(size_t i = 0; i < type->membersSize && ret == UA_STATUSCODE_GOOD; ++i) {
const UA_DataTypeMember *m = &type->members[i];
- const UA_DataType *mt = &typelists[!m->namespaceZero][m->memberTypeIndex];
+ const UA_DataType *mt = m->memberType;
ptr += m->padding;
/* Array. Buffer-exchange is done inside Array_encodeBinary if required. */
@@ -10258,15 +8512,16 @@ encodeBinaryStruct(const void *src, const UA_DataType *type, Ctx *ctx) {
const size_t length = *((const size_t*)ptr);
ptr += sizeof(size_t);
ret = Array_encodeBinary(*(void *UA_RESTRICT const *)ptr, length, mt, ctx);
+ UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
ptr += sizeof(void*);
continue;
}
/* Scalar */
ret = encodeWithExchangeBuffer((const void*)ptr, mt, ctx);
+ UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
ptr += mt->memSize;
}
- UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
ctx->depth--;
return ret;
@@ -10279,15 +8534,13 @@ encodeBinaryStructWithOptFields(const void *src, const UA_DataType *type, Ctx *c
return UA_STATUSCODE_BADENCODINGERROR;
ctx->depth++;
- const UA_DataType *typelists[2] = { UA_TYPES, &type[-type->typeIndex] };
-
/* Creating the encoding mask, marking the available optional fields */
uintptr_t ptr = (uintptr_t)src;
size_t optFieldCounter = 0;
UA_UInt32 encodingMask = 0;
for(size_t j = 0; j < type->membersSize; ++j) {
const UA_DataTypeMember *m = &type->members[j];
- const UA_DataType *mt = &typelists[!m->namespaceZero][m->memberTypeIndex];
+ const UA_DataType *mt = m->memberType;
ptr += m->padding;
if(m->isOptional) {
if(m->isArray)
@@ -10304,17 +8557,14 @@ encodeBinaryStructWithOptFields(const void *src, const UA_DataType *type, Ctx *c
}
/* Encode the mask */
- status ret = UInt32_encodeBinary(&encodingMask, &UA_TYPES[UA_TYPES_UINT32], ctx);
- if(ret != UA_STATUSCODE_GOOD) {
- ctx->depth--;
- return ret;
- }
+ status ret = ENCODE_DIRECT(&encodingMask, UInt32);
+ UA_CHECK_STATUS(ret, ctx->depth--; return ret);
/* Loop over members */
ptr = (uintptr_t)src;
- for(size_t i = 0, o = 0; i < type->membersSize && ret == UA_STATUSCODE_GOOD; ++i) {
+ for(size_t i = 0, o = 0; i < type->membersSize && UA_LIKELY(ret == UA_STATUSCODE_GOOD); ++i) {
const UA_DataTypeMember *m = &type->members[i];
- const UA_DataType *mt = &typelists[!m->namespaceZero][m->memberTypeIndex];
+ const UA_DataType *mt = m->memberType;
ptr += m->padding;
if(m->isOptional) {
@@ -10357,22 +8607,32 @@ encodeBinaryStructWithOptFields(const void *src, const UA_DataType *type, Ctx *c
static status
encodeBinaryUnion(const void *src, const UA_DataType *type, Ctx *ctx) {
/* Check the recursion limit */
- if(ctx->depth > UA_ENCODING_MAX_RECURSION)
- return UA_STATUSCODE_BADENCODINGERROR;
+ UA_CHECK(ctx->depth <= UA_ENCODING_MAX_RECURSION,
+ return UA_STATUSCODE_BADENCODINGERROR);
ctx->depth++;
+ /* Encode the selection */
const UA_UInt32 selection = *(const UA_UInt32*)src;
- status ret = ENCODE_DIRECT(src, UInt32);
- if(ret != UA_STATUSCODE_GOOD || selection == 0) {
+ status ret = ENCODE_DIRECT(&selection, UInt32);
+ if(UA_UNLIKELY(ret != UA_STATUSCODE_GOOD) || selection == 0) {
ctx->depth--;
return ret;
}
- const UA_DataType *typelists[2] = { UA_TYPES, &type[-type->typeIndex] };
+ /* Select the member */
const UA_DataTypeMember *m = &type->members[selection-1];
- const UA_DataType *mt = &typelists[!m->namespaceZero][m->memberTypeIndex];
- uintptr_t ptr = ((uintptr_t)src) + UA_TYPES[UA_TYPES_UINT32].memSize + m->padding;
- ret = encodeWithExchangeBuffer((const void*)ptr, mt, ctx);
+ const UA_DataType *mt = m->memberType;
+
+ /* Encode the member */
+ uintptr_t ptr = ((uintptr_t)src) + m->padding; /* includes the switchfield length */
+ if(!m->isArray) {
+ ret = encodeWithExchangeBuffer((const void*)ptr, mt, ctx);
+ } else {
+ const size_t length = *((const size_t*)ptr);
+ ptr += sizeof(size_t);
+ ret = Array_encodeBinary(*(void *UA_RESTRICT const *)ptr, length, mt, ctx);
+ }
+
UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
ctx->depth--;
@@ -10385,10 +8645,6 @@ encodeBinaryNotImplemented(const void *src, const UA_DataType *type, Ctx *ctx) {
return UA_STATUSCODE_BADNOTIMPLEMENTED;
}
-/********************/
-/* Structured Types */
-/********************/
-
const encodeBinarySignature encodeBinaryJumpTable[UA_DATATYPEKINDS] = {
(encodeBinarySignature)Boolean_encodeBinary,
(encodeBinarySignature)Byte_encodeBinary, /* SByte */
@@ -10424,9 +8680,10 @@ const encodeBinarySignature encodeBinaryJumpTable[UA_DATATYPEKINDS] = {
};
status
-UA_encodeBinary(const void *src, const UA_DataType *type,
- u8 **bufPos, const u8 **bufEnd,
- UA_exchangeEncodeBuffer exchangeCallback, void *exchangeHandle) {
+UA_encodeBinaryInternal(const void *src, const UA_DataType *type,
+ u8 **bufPos, const u8 **bufEnd,
+ UA_exchangeEncodeBuffer exchangeCallback,
+ void *exchangeHandle) {
/* Set up the context */
Ctx ctx;
ctx.pos = *bufPos;
@@ -10435,8 +8692,7 @@ UA_encodeBinary(const void *src, const UA_DataType *type,
ctx.exchangeBufferCallback = exchangeCallback;
ctx.exchangeBufferCallbackHandle = exchangeHandle;
- if(!ctx.pos)
- return UA_STATUSCODE_BADINVALIDARGUMENT;
+ UA_CHECK_MEM(ctx.pos, return UA_STATUSCODE_BADINVALIDARGUMENT);
/* Encode */
status ret = encodeWithExchangeBuffer(src, type, &ctx);
@@ -10449,6 +8705,34 @@ UA_encodeBinary(const void *src, const UA_DataType *type,
return ret;
}
+UA_StatusCode
+UA_encodeBinary(const void *p, const UA_DataType *type,
+ UA_ByteString *outBuf) {
+ /* Allocate buffer */
+ UA_Boolean allocated = false;
+ status res = UA_STATUSCODE_GOOD;
+ if(outBuf->length == 0) {
+ size_t len = UA_calcSizeBinary(p, type);
+ res = UA_ByteString_allocBuffer(outBuf, len);
+ if(res != UA_STATUSCODE_GOOD)
+ return res;
+ allocated = true;
+ }
+
+ /* Encode */
+ u8 *pos = outBuf->data;
+ const u8 *posEnd = &outBuf->data[outBuf->length];
+ res = UA_encodeBinaryInternal(p, type, &pos, &posEnd, NULL, NULL);
+
+ /* Clean up */
+ if(res == UA_STATUSCODE_GOOD) {
+ outBuf->length = (size_t)((uintptr_t)pos - (uintptr_t)outBuf->data);
+ } else if(allocated) {
+ UA_ByteString_clear(outBuf);
+ }
+ return res;
+}
+
static status
decodeBinaryNotImplemented(void *dst, const UA_DataType *type, Ctx *ctx) {
(void)dst, (void)type, (void)ctx;
@@ -10458,19 +8742,18 @@ decodeBinaryNotImplemented(void *dst, const UA_DataType *type, Ctx *ctx) {
static status
decodeBinaryStructure(void *dst, const UA_DataType *type, Ctx *ctx) {
/* Check the recursion limit */
- if(ctx->depth > UA_ENCODING_MAX_RECURSION)
- return UA_STATUSCODE_BADENCODINGERROR;
+ UA_CHECK(ctx->depth <= UA_ENCODING_MAX_RECURSION,
+ return UA_STATUSCODE_BADENCODINGERROR);
ctx->depth++;
uintptr_t ptr = (uintptr_t)dst;
status ret = UA_STATUSCODE_GOOD;
u8 membersSize = type->membersSize;
- const UA_DataType *typelists[2] = { UA_TYPES, &type[-type->typeIndex] };
/* Loop over members */
for(size_t i = 0; i < membersSize && ret == UA_STATUSCODE_GOOD; ++i) {
const UA_DataTypeMember *m = &type->members[i];
- const UA_DataType *mt = &typelists[!m->namespaceZero][m->memberTypeIndex];
+ const UA_DataType *mt = m->memberType;
ptr += m->padding;
/* Array */
@@ -10494,23 +8777,18 @@ decodeBinaryStructure(void *dst, const UA_DataType *type, Ctx *ctx) {
static status
decodeBinaryStructureWithOptFields(void *dst, const UA_DataType *type, Ctx *ctx) {
/* Check the recursion limit */
- if(ctx == NULL || ctx->depth > UA_ENCODING_MAX_RECURSION)
- return UA_STATUSCODE_BADENCODINGERROR;
+ UA_CHECK(ctx->depth <= UA_ENCODING_MAX_RECURSION, return UA_STATUSCODE_BADENCODINGERROR);
ctx->depth++;
uintptr_t ptr = (uintptr_t)dst;
UA_UInt32 encodingMask = 0;
status ret = UInt32_decodeBinary(&encodingMask, &UA_TYPES[UA_TYPES_UINT32], ctx);
- if(ret != UA_STATUSCODE_GOOD) {
- ctx->depth--;
- return ret;
- }
+ UA_CHECK_STATUS(ret, ctx->depth--; return ret);
/* Loop over members */
- const UA_DataType *typelists[2] = { UA_TYPES, &type[-type->typeIndex] };
for(size_t i = 0, o = 0; i < type->membersSize && ret == UA_STATUSCODE_GOOD; ++i) {
const UA_DataTypeMember *m = &type->members[i];
- const UA_DataType *mt = &typelists[!m->namespaceZero][m->memberTypeIndex];
+ const UA_DataType *mt = m->memberType;
ptr += m->padding;
if(m->isOptional) {
if(!(encodingMask & (UA_UInt32) ( (UA_UInt32) 1<<(o++)))) {
@@ -10525,8 +8803,7 @@ decodeBinaryStructureWithOptFields(void *dst, const UA_DataType *type, Ctx *ctx)
} else {
/* Optional Scalar */
*(void *UA_RESTRICT *UA_RESTRICT) ptr = UA_calloc(1, mt->memSize);
- if(!*(void *UA_RESTRICT *UA_RESTRICT) ptr)
- return UA_STATUSCODE_BADOUTOFMEMORY;
+ UA_CHECK_MEM(*(void *UA_RESTRICT *UA_RESTRICT) ptr, return UA_STATUSCODE_BADOUTOFMEMORY);
ret = decodeBinaryJumpTable[mt->typeKind](*(void *UA_RESTRICT *UA_RESTRICT) ptr, mt, ctx);
}
ptr += sizeof(void *);
@@ -10553,26 +8830,36 @@ decodeBinaryStructureWithOptFields(void *dst, const UA_DataType *type, Ctx *ctx)
static status
decodeBinaryUnion(void *UA_RESTRICT dst, const UA_DataType *type, Ctx *ctx) {
/* Check the recursion limit */
- if(ctx->depth > UA_ENCODING_MAX_RECURSION)
- return UA_STATUSCODE_BADENCODINGERROR;
+ UA_CHECK(ctx->depth <= UA_ENCODING_MAX_RECURSION,
+ return UA_STATUSCODE_BADENCODINGERROR);
+ /* Decode the selection directly into the switchfield */
status ret = DECODE_DIRECT(dst, UInt32);
- if(ret != UA_STATUSCODE_GOOD)
- return ret;
+ UA_CHECK_STATUS(ret, return ret);
+ /* No content? */
UA_UInt32 selection = *(UA_UInt32*)dst;
if(selection == 0)
return UA_STATUSCODE_GOOD;
- if(selection-1 >= type->membersSize)
- return UA_STATUSCODE_BADDECODINGERROR;
- const UA_DataType *typelists[2] = { UA_TYPES, &type[-type->typeIndex] };
+ /* Sanity check the selection */
+ UA_CHECK(selection-1 < type->membersSize,
+ return UA_STATUSCODE_BADDECODINGERROR);
+
+ /* Select the member */
const UA_DataTypeMember *m = &type->members[selection-1];
- const UA_DataType *mt = &typelists[!m->namespaceZero][m->memberTypeIndex];
- uintptr_t ptr = ((uintptr_t)dst) + UA_TYPES[UA_TYPES_UINT32].memSize + m->padding;
+ const UA_DataType *mt = m->memberType;
+ /* Decode */
ctx->depth++;
- ret = decodeBinaryJumpTable[mt->typeKind]((void *UA_RESTRICT)ptr, mt, ctx);
+ uintptr_t ptr = ((uintptr_t)dst) + m->padding; /* includes the switchfield */
+ if(!m->isArray) {
+ ret = decodeBinaryJumpTable[mt->typeKind]((void *UA_RESTRICT)ptr, mt, ctx);
+ } else {
+ size_t *length = (size_t *)ptr;
+ ptr += sizeof(size_t);
+ ret = Array_decodeBinary((void *UA_RESTRICT *UA_RESTRICT)ptr, length, mt, ctx);
+ }
ctx->depth--;
return ret;
}
@@ -10612,8 +8899,9 @@ const decodeBinarySignature decodeBinaryJumpTable[UA_DATATYPEKINDS] = {
};
status
-UA_decodeBinary(const UA_ByteString *src, size_t *offset, void *dst,
- const UA_DataType *type, const UA_DataTypeArray *customTypes) {
+UA_decodeBinaryInternal(const UA_ByteString *src, size_t *offset,
+ void *dst, const UA_DataType *type,
+ const UA_DataTypeArray *customTypes) {
/* Set up the context */
Ctx ctx;
ctx.pos = &src->data[*offset];
@@ -10625,7 +8913,7 @@ UA_decodeBinary(const UA_ByteString *src, size_t *offset, void *dst,
memset(dst, 0, type->memSize); /* Initialize the value */
status ret = decodeBinaryJumpTable[type->typeKind](dst, type, &ctx);
- if(ret == UA_STATUSCODE_GOOD) {
+ if(UA_LIKELY(ret == UA_STATUSCODE_GOOD)) {
/* Set the new offset */
*offset = (size_t)(ctx.pos - src->data) / sizeof(u8);
} else {
@@ -10636,6 +8924,15 @@ UA_decodeBinary(const UA_ByteString *src, size_t *offset, void *dst,
return ret;
}
+UA_StatusCode
+UA_decodeBinary(const UA_ByteString *inBuf,
+ void *p, const UA_DataType *type,
+ const UA_DecodeBinaryOptions *options) {
+ size_t offset = 0;
+ const UA_DataTypeArray *customTypes = options ? options->customTypes : NULL;
+ return UA_decodeBinaryInternal(inBuf, &offset, p, type, customTypes);
+}
+
/**
* Compute the Message Size
* ------------------------
@@ -10739,7 +9036,7 @@ CALCSIZE_BINARY(ExtensionObject) {
if(src->content.decoded.type->typeId.identifierType != UA_NODEIDTYPE_NUMERIC)
return 0;
- s += NodeId_calcSizeBinary(&src->content.decoded.type->typeId, NULL); /* Type encoding length */
+ s += NodeId_calcSizeBinary(&src->content.decoded.type->binaryEncodingId, NULL); /* Type encoding length */
s += 4; /* Encoding length field */
const UA_DataType *type = src->content.decoded.type;
s += calcSizeBinaryJumpTable[type->typeKind](src->content.decoded.data, type); /* Encoding length */
@@ -10763,7 +9060,7 @@ CALCSIZE_BINARY(Variant) {
/* The type is wrapped inside an extensionobject */
/* (NodeId + encoding byte + extension object length) * array length */
size_t length = isArray ? src->arrayLength : 1;
- s += (NodeId_calcSizeBinary(&src->type->typeId, NULL) + 1 + 4) * length;
+ s += (NodeId_calcSizeBinary(&src->type->binaryEncodingId, NULL) + 1 + 4) * length;
}
const UA_Boolean hasDimensions = isArray && src->arrayDimensionsSize > 0;
@@ -10814,12 +9111,11 @@ calcSizeBinaryStructure(const void *p, const UA_DataType *type) {
size_t s = 0;
uintptr_t ptr = (uintptr_t)p;
u8 membersSize = type->membersSize;
- const UA_DataType *typelists[2] = { UA_TYPES, &type[-type->typeIndex] };
/* Loop over members */
for(size_t i = 0; i < membersSize; ++i) {
const UA_DataTypeMember *member = &type->members[i];
- const UA_DataType *membertype = &typelists[!member->namespaceZero][member->memberTypeIndex];
+ const UA_DataType *membertype = member->memberType;
ptr += member->padding;
/* Array */
@@ -10846,10 +9142,9 @@ calcSizeBinaryStructureWithOptFields(const void *p, const UA_DataType *type) {
/* Loop over members */
uintptr_t ptr = (uintptr_t)p;
- const UA_DataType *typelists[2] = { UA_TYPES, &type[-type->typeIndex] };
for(size_t i = 0; i < type->membersSize; ++i) {
const UA_DataTypeMember *member = &type->members[i];
- const UA_DataType *membertype = &typelists[!member->namespaceZero][member->memberTypeIndex];
+ const UA_DataType *membertype = member->memberType;
ptr += member->padding;
if(member->isOptional) {
if((member->isArray && ((*(void* const*)(ptr+sizeof(size_t))) == NULL)) ||
@@ -10879,18 +9174,22 @@ calcSizeBinaryStructureWithOptFields(const void *p, const UA_DataType *type) {
static size_t
calcSizeBinaryUnion(const void *p, const UA_DataType *type) {
- size_t s = 0;
- uintptr_t ptr = (uintptr_t)p;
- UA_UInt32 selection = *(UA_UInt32 *) ptr;
+ size_t s = 4; /* UA_TYPES[UA_TYPES_UINT32].memSize; */
+ const UA_UInt32 selection = *(const UA_UInt32 *)p;
if(selection == 0)
- return UA_TYPES[UA_TYPES_UINT32].memSize;
- const UA_DataType *typelists[2] = { UA_TYPES, &type[-type->typeIndex] };
+ return s;
+
const UA_DataTypeMember *m = &type->members[selection-1];
- const UA_DataType *mt = &typelists[!m->namespaceZero][m->memberTypeIndex];
- s += UA_TYPES[UA_TYPES_UINT32].memSize;
- ptr += UA_TYPES[UA_TYPES_UINT32].memSize;
- ptr += m->padding;
- s += UA_calcSizeBinary((const void *) ptr, mt);
+ const UA_DataType *mt = m->memberType;
+
+ uintptr_t ptr = ((uintptr_t)p) + m->padding; /* includes switchfield length */
+ if(!m->isArray) {
+ s += UA_calcSizeBinary((const void*)ptr, mt);
+ } else {
+ const size_t length = *((const size_t*)ptr);
+ ptr += sizeof(size_t);
+ s += Array_calcSizeBinary(*(void *UA_RESTRICT const *)ptr, length, mt);
+ }
return s;
}
@@ -10939,10 +9238,818 @@ UA_calcSizeBinary(const void *p, const UA_DataType *type) {
return calcSizeBinaryJumpTable[type->typeKind](p, type);
}
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/build/src_generated/open62541/types_generated.c" ***********************************/
+/**** amalgamated original file "/src/ua_types_print.c" ****/
+
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Copyright 2020 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
+ */
+
+
+
+/* Printing of NodeIds is always enabled. We need it for logging. */
+
+UA_StatusCode
+UA_NodeId_print(const UA_NodeId *id, UA_String *output) {
+ UA_String_clear(output);
+ if(!id)
+ return UA_STATUSCODE_GOOD;
+
+ char *nsStr = NULL;
+ long snprintfLen = 0;
+ size_t nsLen = 0;
+ if(id->namespaceIndex != 0) {
+ nsStr = (char*)UA_malloc(9+1); // strlen("ns=XXXXX;") = 9 + Nullbyte
+ if(!nsStr)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ snprintfLen = UA_snprintf(nsStr, 10, "ns=%d;", id->namespaceIndex);
+ if(snprintfLen < 0 || snprintfLen >= 10) {
+ UA_free(nsStr);
+ return UA_STATUSCODE_BADINTERNALERROR;
+ }
+ nsLen = (size_t)(snprintfLen);
+ }
+
+ UA_ByteString byteStr = UA_BYTESTRING_NULL;
+ switch (id->identifierType) {
+ case UA_NODEIDTYPE_NUMERIC:
+ /* ns (2 byte, 65535) = 5 chars, numeric (4 byte, 4294967295) = 10
+ * chars, delim = 1 , nullbyte = 1-> 17 chars */
+ output->length = nsLen + 2 + 10 + 1;
+ output->data = (UA_Byte*)UA_malloc(output->length);
+ if(output->data == NULL) {
+ output->length = 0;
+ UA_free(nsStr);
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ }
+ snprintfLen = UA_snprintf((char*)output->data, output->length, "%si=%lu",
+ nsLen > 0 ? nsStr : "",
+ (unsigned long )id->identifier.numeric);
+ break;
+ case UA_NODEIDTYPE_STRING:
+ /* ns (16bit) = 5 chars, strlen + nullbyte */
+ output->length = nsLen + 2 + id->identifier.string.length + 1;
+ output->data = (UA_Byte*)UA_malloc(output->length);
+ if(output->data == NULL) {
+ output->length = 0;
+ UA_free(nsStr);
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ }
+ snprintfLen = UA_snprintf((char*)output->data, output->length, "%ss=%.*s",
+ nsLen > 0 ? nsStr : "", (int)id->identifier.string.length,
+ id->identifier.string.data);
+ break;
+ case UA_NODEIDTYPE_GUID:
+ /* ns (16bit) = 5 chars + strlen(A123456C-0ABC-1A2B-815F-687212AAEE1B)=36 + nullbyte */
+ output->length = nsLen + 2 + 36 + 1;
+ output->data = (UA_Byte*)UA_malloc(output->length);
+ if(output->data == NULL) {
+ output->length = 0;
+ UA_free(nsStr);
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ }
+ snprintfLen = UA_snprintf((char*)output->data, output->length,
+ "%sg=" UA_PRINTF_GUID_FORMAT, nsLen > 0 ? nsStr : "",
+ UA_PRINTF_GUID_DATA(id->identifier.guid));
+ break;
+ case UA_NODEIDTYPE_BYTESTRING:
+ UA_ByteString_toBase64(&id->identifier.byteString, &byteStr);
+ /* ns (16bit) = 5 chars + LEN + nullbyte */
+ output->length = nsLen + 2 + byteStr.length + 1;
+ output->data = (UA_Byte*)UA_malloc(output->length);
+ if(output->data == NULL) {
+ output->length = 0;
+ UA_String_clear(&byteStr);
+ UA_free(nsStr);
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ }
+ snprintfLen = UA_snprintf((char*)output->data, output->length, "%sb=%.*s",
+ nsLen > 0 ? nsStr : "",
+ (int)byteStr.length, byteStr.data);
+ UA_String_clear(&byteStr);
+ break;
+ }
+ UA_free(nsStr);
+
+ if(snprintfLen < 0 || snprintfLen >= (long) output->length) {
+ UA_free(output->data);
+ output->data = NULL;
+ output->length = 0;
+ return UA_STATUSCODE_BADINTERNALERROR;
+ }
+ output->length = (size_t)snprintfLen;
+
+ return UA_STATUSCODE_GOOD;
+}
+
+UA_StatusCode
+UA_ExpandedNodeId_print(const UA_ExpandedNodeId *id, UA_String *output) {
+ /* Don't print the namespace-index if a NamespaceUri is set */
+ UA_NodeId nid = id->nodeId;
+ if(id->namespaceUri.data != NULL)
+ nid.namespaceIndex = 0;
+
+ /* Encode the NodeId */
+ UA_String outNid = UA_STRING_NULL;
+ UA_StatusCode res = UA_NodeId_print(&nid, &outNid);
+ if(res != UA_STATUSCODE_GOOD)
+ return res;
+
+ /* Encode the ServerIndex */
+ char svr[100];
+ if(id->serverIndex == 0)
+ svr[0] = 0;
+ else
+ UA_snprintf(svr, 100, "svr=%"PRIu32";", id->serverIndex);
+ size_t svrlen = strlen(svr);
+
+ /* Encode the NamespaceUri */
+ char nsu[100];
+ if(id->namespaceUri.data == NULL)
+ nsu[0] = 0;
+ else
+ UA_snprintf(nsu, 100, "nsu=%.*s;", (int)id->namespaceUri.length, id->namespaceUri.data);
+ size_t nsulen = strlen(nsu);
+
+ /* Combine everything */
+ res = UA_ByteString_allocBuffer((UA_String*)output, outNid.length + svrlen + nsulen);
+ if(res == UA_STATUSCODE_GOOD) {
+ memcpy(output->data, svr, svrlen);
+ memcpy(&output->data[svrlen], nsu, nsulen);
+ memcpy(&output->data[svrlen+nsulen], outNid.data, outNid.length);
+ }
+
+ UA_String_clear(&outNid);
+ return res;
+}
+
+#ifdef UA_ENABLE_TYPEDESCRIPTION
+
+/***********************/
+/* Jumptable Signature */
+/***********************/
+
+typedef struct UA_PrintElement {
+ TAILQ_ENTRY(UA_PrintElement) next;
+ size_t length;
+ UA_Byte data[];
+} UA_PrintOutput;
+
+typedef struct {
+ size_t depth;
+ TAILQ_HEAD(, UA_PrintElement) outputs;
+} UA_PrintContext;
+
+typedef UA_StatusCode
+(*UA_printSignature)(UA_PrintContext *ctx, const void *p,
+ const UA_DataType *type);
+
+extern const UA_printSignature printJumpTable[UA_DATATYPEKINDS];
+
+/********************/
+/* Helper Functions */
+/********************/
+
+static UA_PrintOutput *
+UA_PrintContext_addOutput(UA_PrintContext *ctx, size_t length) {
+ /* Protect against overlong output in pretty-printing */
+ if(length > 2<<16)
+ return NULL;
+ UA_PrintOutput *output = (UA_PrintOutput*)UA_malloc(sizeof(UA_PrintOutput) + length + 1);
+ if(!output)
+ return NULL;
+ output->length = length;
+ TAILQ_INSERT_TAIL(&ctx->outputs, output, next);
+ return output;
+}
+
+static UA_StatusCode
+UA_PrintContext_addNewlineTabs(UA_PrintContext *ctx, size_t tabs) {
+ UA_PrintOutput *out = UA_PrintContext_addOutput(ctx, tabs+1);
+ if(!out)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ out->data[0] = '\n';
+ for(size_t i = 1; i <= tabs; i++)
+ out->data[i] = '\t';
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_StatusCode
+UA_PrintContext_addName(UA_PrintContext *ctx, const char *name) {
+ size_t nameLen = strlen(name);
+ UA_PrintOutput *out = UA_PrintContext_addOutput(ctx, nameLen+2);
+ if(!out)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ memcpy(&out->data, name, nameLen);
+ out->data[nameLen] = ':';
+ out->data[nameLen+1] = ' ';
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_StatusCode
+UA_PrintContext_addString(UA_PrintContext *ctx, const char *str) {
+ size_t len = strlen(str);
+ UA_PrintOutput *out = UA_PrintContext_addOutput(ctx, len);
+ if(!out)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ memcpy(&out->data, str, len);
+ return UA_STATUSCODE_GOOD;
+}
+
+/*********************/
+/* Printing Routines */
+/*********************/
+
+static UA_StatusCode
+printArray(UA_PrintContext *ctx, const void *p, const size_t length,
+ const UA_DataType *type);
+
+static UA_StatusCode
+printBoolean(UA_PrintContext *ctx, const UA_Boolean *p, const UA_DataType *_) {
+ if(*p)
+ return UA_PrintContext_addString(ctx, "true");
+ return UA_PrintContext_addString(ctx, "false");
+}
+
+static UA_StatusCode
+printSByte(UA_PrintContext *ctx, const UA_SByte *p, const UA_DataType *_) {
+ char out[32];
+ UA_snprintf(out, 32, "%"PRIi8, *p);
+ return UA_PrintContext_addString(ctx, out);
+}
+
+static UA_StatusCode
+printByte(UA_PrintContext *ctx, const UA_Byte *p, const UA_DataType *_) {
+ char out[32];
+ UA_snprintf(out, 32, "%"PRIu8, *p);
+ return UA_PrintContext_addString(ctx, out);
+}
+
+static UA_StatusCode
+printInt16(UA_PrintContext *ctx, const UA_Int16 *p, const UA_DataType *_) {
+ char out[32];
+ UA_snprintf(out, 32, "%"PRIi16, *p);
+ return UA_PrintContext_addString(ctx, out);
+}
+
+static UA_StatusCode
+printUInt16(UA_PrintContext *ctx, const UA_UInt16 *p, const UA_DataType *_) {
+ char out[32];
+ UA_snprintf(out, 32, "%"PRIu16, *p);
+ return UA_PrintContext_addString(ctx, out);
+}
+
+static UA_StatusCode
+printInt32(UA_PrintContext *ctx, const UA_Int32 *p, const UA_DataType *_) {
+ char out[32];
+ UA_snprintf(out, 32, "%"PRIi32, *p);
+ return UA_PrintContext_addString(ctx, out);
+}
+
+static UA_StatusCode
+printUInt32(UA_PrintContext *ctx, const UA_UInt32 *p, const UA_DataType *_) {
+ char out[32];
+ UA_snprintf(out, 32, "%"PRIu32, *p);
+ return UA_PrintContext_addString(ctx, out);
+}
+
+static UA_StatusCode
+printInt64(UA_PrintContext *ctx, const UA_Int64 *p, const UA_DataType *_) {
+ char out[64];
+ UA_snprintf(out, 64, "%"PRIi64, *p);
+ return UA_PrintContext_addString(ctx, out);
+}
+
+static UA_StatusCode
+printUInt64(UA_PrintContext *ctx, const UA_UInt64 *p, const UA_DataType *_) {
+ char out[64];
+ UA_snprintf(out, 64, "%"PRIu64, *p);
+ return UA_PrintContext_addString(ctx, out);
+}
+
+static UA_StatusCode
+printFloat(UA_PrintContext *ctx, const UA_Float *p, const UA_DataType *_) {
+ char out[64];
+ UA_snprintf(out, 32, "%f", *p);
+ return UA_PrintContext_addString(ctx, out);
+}
+
+static UA_StatusCode
+printDouble(UA_PrintContext *ctx, const UA_Double *p, const UA_DataType *_) {
+ char out[64];
+ UA_snprintf(out, 64, "%lf", *p);
+ return UA_PrintContext_addString(ctx, out);
+}
+
+static UA_StatusCode
+printStatusCode(UA_PrintContext *ctx, const UA_StatusCode *p, const UA_DataType *_) {
+ return UA_PrintContext_addString(ctx, UA_StatusCode_name(*p));
+}
+
+static UA_StatusCode
+printNodeId(UA_PrintContext *ctx, const UA_NodeId *p, const UA_DataType *_) {
+ UA_String out;
+ UA_String_init(&out);
+ UA_StatusCode res = UA_NodeId_print(p, &out);
+ if(res != UA_STATUSCODE_GOOD)
+ return res;
+ UA_PrintOutput *po = UA_PrintContext_addOutput(ctx, out.length);
+ if(po)
+ memcpy(po->data, out.data, out.length);
+ else
+ res = UA_STATUSCODE_BADOUTOFMEMORY;
+ UA_String_clear(&out);
+ return res;
+}
+
+static UA_StatusCode
+printExpandedNodeId(UA_PrintContext *ctx, const UA_ExpandedNodeId *p, const UA_DataType *_) {
+ UA_String out;
+ UA_String_init(&out);
+ UA_StatusCode res = UA_ExpandedNodeId_print(p, &out);
+ if(res != UA_STATUSCODE_GOOD)
+ return res;
+ UA_PrintOutput *po = UA_PrintContext_addOutput(ctx, out.length);
+ if(!po)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ memcpy(po->data, out.data, out.length);
+ UA_String_clear(&out);
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_StatusCode
+printDateTime(UA_PrintContext *ctx, const UA_DateTime *p, const UA_DataType *_) {
+ UA_Int64 tOffset = UA_DateTime_localTimeUtcOffset();
+ UA_DateTimeStruct dts = UA_DateTime_toStruct(*p);
+ char dateString[100];
+ UA_snprintf((char*)dateString, 100,
+ "%04u-%02u-%02u %02u:%02u:%02u.%03u (UTC%+05d)",
+ dts.year, dts.month, dts.day, dts.hour, dts.min,
+ dts.sec, dts.milliSec,
+ (int)(tOffset / UA_DATETIME_SEC / 36));
+ return UA_PrintContext_addString(ctx, dateString);
+}
+
+static UA_StatusCode
+printGuid(UA_PrintContext *ctx, const UA_Guid *p, const UA_DataType *_) {
+ char tmp[100];
+ UA_snprintf(tmp, 100, UA_PRINTF_GUID_FORMAT, UA_PRINTF_GUID_DATA(*p));
+ return UA_PrintContext_addString(ctx, tmp);
+}
+
+static UA_StatusCode
+printString(UA_PrintContext *ctx, const UA_String *p, const UA_DataType *_) {
+ if(!p->data)
+ return UA_PrintContext_addString(ctx, "NullString");
+ UA_PrintOutput *out = UA_PrintContext_addOutput(ctx, p->length+2);
+ if(!out)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ UA_snprintf((char*)out->data, p->length+3, "\"%.*s\"", (int)p->length, p->data);
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_StatusCode
+printByteString(UA_PrintContext *ctx, const UA_ByteString *p, const UA_DataType *_) {
+ if(!p->data)
+ return UA_PrintContext_addString(ctx, "NullByteString");
+ UA_String str = UA_BYTESTRING_NULL;
+ UA_StatusCode res = UA_ByteString_toBase64(p, &str);
+ if(res != UA_STATUSCODE_GOOD)
+ return res;
+ res = printString(ctx, &str, NULL);
+ UA_String_clear(&str);
+ return res;
+}
+
+static UA_StatusCode
+printQualifiedName(UA_PrintContext *ctx, const UA_QualifiedName *p, const UA_DataType *_) {
+ UA_StatusCode retval = UA_STATUSCODE_GOOD;
+ retval |= UA_PrintContext_addString(ctx, "{");
+ ctx->depth++;
+ retval |= UA_PrintContext_addNewlineTabs(ctx, ctx->depth);
+ retval |= UA_PrintContext_addName(ctx, "NamespaceIndex");
+ retval |= printUInt16(ctx, &p->namespaceIndex, NULL);
+ retval |= UA_PrintContext_addString(ctx, ",");
+ retval |= UA_PrintContext_addNewlineTabs(ctx, ctx->depth);
+ retval |= UA_PrintContext_addName(ctx, "Name");
+ retval |= printString(ctx, &p->name, NULL);
+ ctx->depth--;
+ retval |= UA_PrintContext_addNewlineTabs(ctx, ctx->depth);
+ retval |= UA_PrintContext_addString(ctx, "}");
+ return retval;
+}
+
+static UA_StatusCode
+printLocalizedText(UA_PrintContext *ctx, const UA_LocalizedText *p, const UA_DataType *_) {
+ UA_StatusCode retval = UA_STATUSCODE_GOOD;
+ retval |= UA_PrintContext_addString(ctx, "{");
+ ctx->depth++;
+ retval |= UA_PrintContext_addNewlineTabs(ctx, ctx->depth);
+ retval |= UA_PrintContext_addName(ctx, "Locale");
+ retval |= printString(ctx, &p->locale, NULL);
+ retval |= UA_PrintContext_addString(ctx, ",");
+ retval |= UA_PrintContext_addNewlineTabs(ctx, ctx->depth);
+ retval |= UA_PrintContext_addName(ctx, "Text");
+ retval |= printString(ctx, &p->text, NULL);
+ ctx->depth--;
+ retval |= UA_PrintContext_addNewlineTabs(ctx, ctx->depth);
+ retval |= UA_PrintContext_addString(ctx, "}");
+ return retval;
+}
+
+static UA_StatusCode
+printVariant(UA_PrintContext *ctx, const UA_Variant *p, const UA_DataType *_) {
+ if(!p->type)
+ return UA_PrintContext_addString(ctx, "NullVariant");
+
+ UA_StatusCode retval = UA_STATUSCODE_GOOD;
+ retval |= UA_PrintContext_addString(ctx, "{");
+ ctx->depth++;
+
+ retval |= UA_PrintContext_addNewlineTabs(ctx, ctx->depth);
+ retval |= UA_PrintContext_addName(ctx, "DataType");
+ retval |= UA_PrintContext_addString(ctx, p->type->typeName);
+ retval |= UA_PrintContext_addString(ctx, ",");
+
+ retval |= UA_PrintContext_addNewlineTabs(ctx, ctx->depth);
+ retval |= UA_PrintContext_addName(ctx, "Value");
+ if(UA_Variant_isScalar(p))
+ retval |= printJumpTable[p->type->typeKind](ctx, p->data, p->type);
+ else
+ retval |= printArray(ctx, p->data, p->arrayLength, p->type);
+
+ if(p->arrayDimensionsSize > 0) {
+ retval |= UA_PrintContext_addString(ctx, ",");
+ retval |= UA_PrintContext_addNewlineTabs(ctx, ctx->depth);
+ retval |= UA_PrintContext_addName(ctx, "ArrayDimensions");
+ retval |= printArray(ctx, p->arrayDimensions, p->arrayDimensionsSize,
+ &UA_TYPES[UA_TYPES_UINT32]);
+ }
+
+ ctx->depth--;
+ retval |= UA_PrintContext_addNewlineTabs(ctx, ctx->depth);
+ retval |= UA_PrintContext_addString(ctx, "}");
+ return retval;
+}
+
+static UA_StatusCode
+printExtensionObject(UA_PrintContext *ctx, const UA_ExtensionObject*p,
+ const UA_DataType *_) {
+ UA_StatusCode res = UA_STATUSCODE_GOOD;
+ switch(p->encoding) {
+ case UA_EXTENSIONOBJECT_ENCODED_NOBODY:
+ return UA_PrintContext_addString(ctx, "ExtensionObject(No Body)");
+ case UA_EXTENSIONOBJECT_ENCODED_BYTESTRING:
+ res |= UA_PrintContext_addString(ctx, "ExtensionObject(Binary Encoded) {");
+ ctx->depth++;
+ res |= UA_PrintContext_addNewlineTabs(ctx, ctx->depth);
+ res |= UA_PrintContext_addName(ctx, "DataType");
+ res |= printNodeId(ctx, &p->content.encoded.typeId, NULL);
+ res |= UA_PrintContext_addString(ctx, ",");
+ res |= UA_PrintContext_addNewlineTabs(ctx, ctx->depth);
+ res |= UA_PrintContext_addName(ctx, "Body");
+ res |= printByteString(ctx, &p->content.encoded.body, NULL);
+ ctx->depth--;
+ res |= UA_PrintContext_addNewlineTabs(ctx, ctx->depth);
+ res |= UA_PrintContext_addName(ctx, "}");
+ break;
+ case UA_EXTENSIONOBJECT_ENCODED_XML:
+ res |= UA_PrintContext_addString(ctx, "ExtensionObject(XML Encoded) {");
+ ctx->depth++;
+ res |= UA_PrintContext_addNewlineTabs(ctx, ctx->depth);
+ res |= UA_PrintContext_addName(ctx, "DataType");
+ res |= printNodeId(ctx, &p->content.encoded.typeId, NULL);
+ res |= UA_PrintContext_addString(ctx, ",");
+ res |= UA_PrintContext_addNewlineTabs(ctx, ctx->depth);
+ res |= UA_PrintContext_addName(ctx, "Body");
+ res |= printString(ctx, (const UA_String*)&p->content.encoded.body, NULL);
+ ctx->depth--;
+ res |= UA_PrintContext_addNewlineTabs(ctx, ctx->depth);
+ res |= UA_PrintContext_addName(ctx, "}");
+ break;
+ case UA_EXTENSIONOBJECT_DECODED:
+ case UA_EXTENSIONOBJECT_DECODED_NODELETE:
+ res |= UA_PrintContext_addString(ctx, "ExtensionObject {");
+ ctx->depth++;
+ res |= UA_PrintContext_addNewlineTabs(ctx, ctx->depth);
+ res |= UA_PrintContext_addName(ctx, "DataType");
+ res |= UA_PrintContext_addString(ctx, p->content.decoded.type->typeName);
+ res |= UA_PrintContext_addString(ctx, ",");
+ res |= UA_PrintContext_addNewlineTabs(ctx, ctx->depth);
+ res |= UA_PrintContext_addName(ctx, "Body");
+ res |= printJumpTable[p->content.decoded.type->typeKind](ctx,
+ p->content.decoded.data,
+ p->content.decoded.type);
+ ctx->depth--;
+ res |= UA_PrintContext_addNewlineTabs(ctx, ctx->depth);
+ res |= UA_PrintContext_addName(ctx, "}");
+ break;
+ default:
+ res = UA_STATUSCODE_BADINTERNALERROR;
+ break;
+ }
+ return res;
+}
-/* Generated from Opc.Ua.Types.bsd with script /home/pdie/sonstiges/qtopcua/repos/open62541/tools/generate_datatypes.py
- * on host mintaka by user pdie at 2021-06-21 11:34:37 */
+static UA_StatusCode
+printDataValue(UA_PrintContext *ctx, const UA_DataValue *p, const UA_DataType *_) {
+ UA_StatusCode retval = UA_STATUSCODE_GOOD;
+ retval |= UA_PrintContext_addString(ctx, "{");
+ ctx->depth++;
+ UA_Boolean comma = false;
+
+ if(p->hasValue) {
+ retval |= UA_PrintContext_addNewlineTabs(ctx, ctx->depth);
+ retval |= UA_PrintContext_addName(ctx, "Value");
+ retval |= printVariant(ctx, &p->value, NULL);
+ comma = true;
+ }
+
+ if(p->hasStatus) {
+ if(comma)
+ retval |= UA_PrintContext_addString(ctx, ",");
+ retval |= UA_PrintContext_addNewlineTabs(ctx, ctx->depth);
+ retval |= UA_PrintContext_addName(ctx, "Status");
+ retval |= printStatusCode(ctx, &p->status, NULL);
+ comma = true;
+ }
+
+ if(p->hasSourceTimestamp) {
+ if(comma)
+ retval |= UA_PrintContext_addString(ctx, ",");
+ retval |= UA_PrintContext_addNewlineTabs(ctx, ctx->depth);
+ retval |= UA_PrintContext_addName(ctx, "SourceTimestamp");
+ retval |= printDateTime(ctx, &p->sourceTimestamp, NULL);
+ comma = true;
+ }
+
+ if(p->hasSourcePicoseconds) {
+ if(comma)
+ retval |= UA_PrintContext_addString(ctx, ",");
+ retval |= UA_PrintContext_addNewlineTabs(ctx, ctx->depth);
+ retval |= UA_PrintContext_addName(ctx, "SourcePicoseconds");
+ retval |= printUInt16(ctx, &p->sourcePicoseconds, NULL);
+ comma = true;
+ }
+
+ if(p->hasServerTimestamp) {
+ if(comma)
+ retval |= UA_PrintContext_addString(ctx, ",");
+ retval |= UA_PrintContext_addNewlineTabs(ctx, ctx->depth);
+ retval |= UA_PrintContext_addName(ctx, "ServerTimestamp");
+ retval |= printDateTime(ctx, &p->serverTimestamp, NULL);
+ comma = true;
+ }
+
+ if(p->hasServerPicoseconds) {
+ if(comma)
+ retval |= UA_PrintContext_addString(ctx, ",");
+ retval |= UA_PrintContext_addNewlineTabs(ctx, ctx->depth);
+ retval |= UA_PrintContext_addName(ctx, "ServerPicoseconds");
+ retval |= printUInt16(ctx, &p->serverPicoseconds, NULL);
+ comma = true;
+ }
+
+ ctx->depth--;
+ if(comma) {
+ retval |= UA_PrintContext_addNewlineTabs(ctx, ctx->depth);
+ retval |= UA_PrintContext_addString(ctx, "}");
+ } else {
+ retval |= UA_PrintContext_addString(ctx, " }");
+ }
+ return retval;
+}
+
+static UA_StatusCode
+printDiagnosticInfo(UA_PrintContext *ctx, const UA_DiagnosticInfo *p, const UA_DataType *_) {
+ UA_StatusCode retval = UA_STATUSCODE_GOOD;
+ retval |= UA_PrintContext_addString(ctx, "{");
+ ctx->depth++;
+ UA_Boolean comma = false;
+
+ if(p->hasSymbolicId) {
+ retval |= UA_PrintContext_addNewlineTabs(ctx, ctx->depth);
+ retval |= UA_PrintContext_addName(ctx, "SymbolicId");
+ retval |= printInt32(ctx, &p->symbolicId, NULL);
+ comma = true;
+ }
+
+ if(p->hasNamespaceUri) {
+ if(comma)
+ retval |= UA_PrintContext_addString(ctx, ",");
+ retval |= UA_PrintContext_addNewlineTabs(ctx, ctx->depth);
+ retval |= UA_PrintContext_addName(ctx, "NamespaceUri");
+ retval |= printInt32(ctx, &p->namespaceUri, NULL);
+ comma = true;
+ }
+
+ if(p->hasLocalizedText) {
+ if(comma)
+ retval |= UA_PrintContext_addString(ctx, ",");
+ retval |= UA_PrintContext_addNewlineTabs(ctx, ctx->depth);
+ retval |= UA_PrintContext_addName(ctx, "LocalizedText");
+ retval |= printInt32(ctx, &p->localizedText, NULL);
+ comma = true;
+ }
+
+ if(p->hasLocale) {
+ if(comma)
+ retval |= UA_PrintContext_addString(ctx, ",");
+ retval |= UA_PrintContext_addNewlineTabs(ctx, ctx->depth);
+ retval |= UA_PrintContext_addName(ctx, "Locale");
+ retval |= printInt32(ctx, &p->locale, NULL);
+ comma = true;
+ }
+
+ if(p->hasAdditionalInfo) {
+ if(comma)
+ retval |= UA_PrintContext_addString(ctx, ",");
+ retval |= UA_PrintContext_addNewlineTabs(ctx, ctx->depth);
+ retval |= UA_PrintContext_addName(ctx, "AdditionalInfo");
+ retval |= printString(ctx, &p->additionalInfo, NULL);
+ comma = true;
+ }
+
+ if(p->hasInnerStatusCode) {
+ if(comma)
+ retval |= UA_PrintContext_addString(ctx, ",");
+ retval |= UA_PrintContext_addNewlineTabs(ctx, ctx->depth);
+ retval |= UA_PrintContext_addName(ctx, "InnerStatusCode");
+ retval |= printStatusCode(ctx, &p->innerStatusCode, NULL);
+ comma = true;
+ }
+
+ if(p->hasInnerDiagnosticInfo) {
+ if(comma)
+ retval |= UA_PrintContext_addString(ctx, ",");
+ retval |= UA_PrintContext_addNewlineTabs(ctx, ctx->depth);
+ retval |= UA_PrintContext_addName(ctx, "InnerDiagnosticInfo");
+ retval |= printDiagnosticInfo(ctx, p->innerDiagnosticInfo, NULL);
+ comma = true;
+ }
+
+ ctx->depth--;
+ if(comma) {
+ retval |= UA_PrintContext_addNewlineTabs(ctx, ctx->depth);
+ retval |= UA_PrintContext_addString(ctx, "}");
+ } else {
+ retval |= UA_PrintContext_addString(ctx, " }");
+ }
+ return retval;
+}
+
+static UA_StatusCode
+printArray(UA_PrintContext *ctx, const void *p, const size_t length,
+ const UA_DataType *type) {
+ UA_StatusCode retval = UA_STATUSCODE_GOOD;
+ if(!p) {
+ retval |= UA_PrintContext_addString(ctx, "Array(-1, ");
+ retval |= UA_PrintContext_addString(ctx, type->typeName);
+ retval |= UA_PrintContext_addString(ctx, ")");
+ return retval;
+ }
+
+ UA_UInt32 length32 = (UA_UInt32)length;
+ retval |= UA_PrintContext_addString(ctx, "Array(");
+ retval |= printUInt32(ctx, &length32, NULL);
+ retval |= UA_PrintContext_addString(ctx, ", ");
+ retval |= UA_PrintContext_addString(ctx, type->typeName);
+ retval |= UA_PrintContext_addString(ctx, ") {");
+ ctx->depth++;
+ uintptr_t target = (uintptr_t)p;
+ for(UA_UInt32 i = 0; i < length; i++) {
+ UA_PrintContext_addNewlineTabs(ctx, ctx->depth);
+ printUInt32(ctx, &i, NULL);
+ retval |= UA_PrintContext_addString(ctx, ": ");
+ printJumpTable[type->typeKind](ctx, (const void*)target, type);
+ if(i < length - 1)
+ retval |= UA_PrintContext_addString(ctx, ",");
+ target += type->memSize;
+ }
+ ctx->depth--;
+ UA_PrintContext_addNewlineTabs(ctx, ctx->depth);
+ retval |= UA_PrintContext_addString(ctx, "}");
+ return retval;
+}
+
+static UA_StatusCode
+printStructure(UA_PrintContext *ctx, const void *p, const UA_DataType *type) {
+ UA_StatusCode retval = UA_STATUSCODE_GOOD;
+ uintptr_t ptrs = (uintptr_t)p;
+ retval |= UA_PrintContext_addString(ctx, "{");
+ ctx->depth++;
+ for(size_t i = 0; i < type->membersSize; ++i) {
+ UA_PrintContext_addNewlineTabs(ctx, ctx->depth);
+ const UA_DataTypeMember *m = &type->members[i];
+ const UA_DataType *mt = m->memberType;
+ ptrs += m->padding;
+ retval |= UA_PrintContext_addName(ctx, m->memberName);
+ if(!m->isArray) {
+ retval |= printJumpTable[mt->typeKind](ctx, (const void *)ptrs, mt);
+ ptrs += mt->memSize;
+ } else {
+ const size_t size = *((const size_t*)ptrs);
+ ptrs += sizeof(size_t);
+ retval |= printArray(ctx, *(void* const*)ptrs, size, mt);
+ ptrs += sizeof(void*);
+ }
+ if(i < (size_t)(type->membersSize - 1))
+ retval |= UA_PrintContext_addString(ctx, ",");
+ }
+ ctx->depth--;
+ UA_PrintContext_addNewlineTabs(ctx, ctx->depth);
+ retval |= UA_PrintContext_addString(ctx, "}");
+ return retval;
+}
+
+static UA_StatusCode
+printNotImplemented(UA_PrintContext *ctx, const void *p, const UA_DataType *type) {
+ UA_StatusCode res = UA_STATUSCODE_GOOD;
+ res |= UA_PrintContext_addString(ctx, type->typeName);
+ res |= UA_PrintContext_addString(ctx, " (Printing Not Implemented)");
+ return res;
+}
+
+const UA_printSignature printJumpTable[UA_DATATYPEKINDS] = {
+ (UA_printSignature)printBoolean,
+ (UA_printSignature)printSByte,
+ (UA_printSignature)printByte,
+ (UA_printSignature)printInt16,
+ (UA_printSignature)printUInt16,
+ (UA_printSignature)printInt32,
+ (UA_printSignature)printUInt32,
+ (UA_printSignature)printInt64,
+ (UA_printSignature)printUInt64,
+ (UA_printSignature)printFloat,
+ (UA_printSignature)printDouble,
+ (UA_printSignature)printString,
+ (UA_printSignature)printDateTime,
+ (UA_printSignature)printGuid,
+ (UA_printSignature)printByteString,
+ (UA_printSignature)printString, /* XmlElement */
+ (UA_printSignature)printNodeId,
+ (UA_printSignature)printExpandedNodeId,
+ (UA_printSignature)printStatusCode,
+ (UA_printSignature)printQualifiedName,
+ (UA_printSignature)printLocalizedText,
+ (UA_printSignature)printExtensionObject,
+ (UA_printSignature)printDataValue,
+ (UA_printSignature)printVariant,
+ (UA_printSignature)printDiagnosticInfo,
+ (UA_printSignature)printNotImplemented, /* Decimal */
+ (UA_printSignature)printUInt32, /* Enumeration */
+ (UA_printSignature)printStructure,
+ (UA_printSignature)printNotImplemented, /* Structure with Optional Fields */
+ (UA_printSignature)printNotImplemented, /* Union */
+ (UA_printSignature)printNotImplemented /* BitfieldCluster*/
+};
+
+UA_StatusCode
+UA_print(const void *p, const UA_DataType *type, UA_String *output) {
+ UA_PrintContext ctx;
+ ctx.depth = 0;
+ TAILQ_INIT(&ctx.outputs);
+
+ /* Encode */
+ UA_StatusCode retval = printJumpTable[type->typeKind](&ctx, p, type);
+
+ /* Allocate memory for the output */
+ if(retval == UA_STATUSCODE_GOOD) {
+ size_t total = 0;
+ UA_PrintOutput *out;
+ TAILQ_FOREACH(out, &ctx.outputs, next)
+ total += out->length;
+ retval = UA_ByteString_allocBuffer((UA_String*)output, total);
+ }
+
+ /* Write the output */
+ if(retval == UA_STATUSCODE_GOOD) {
+ size_t pos = 0;
+ UA_PrintOutput *out;
+ TAILQ_FOREACH(out, &ctx.outputs, next) {
+ memcpy(&output->data[pos], out->data, out->length);
+ pos += out->length;
+ }
+ }
+
+ /* Free the context */
+ UA_PrintOutput *o, *o2;
+ TAILQ_FOREACH_SAFE(o, &ctx.outputs, next, o2) {
+ TAILQ_REMOVE(&ctx.outputs, o, next);
+ UA_free(o);
+ }
+ return retval;
+}
+
+#endif /* UA_ENABLE_TYPEDESCRIPTION */
+
+/**** amalgamated original file "/build/src_generated/open62541/types_generated.c" ****/
+
+/**********************************
+ * Autogenerated -- do not modify *
+ **********************************/
/* Boolean */
@@ -11020,6 +10127,23 @@ UA_calcSizeBinary(const void *p, const UA_DataType *type) {
/* DiagnosticInfo */
#define DiagnosticInfo_members NULL
+/* KeyValuePair */
+static UA_DataTypeMember KeyValuePair_members[2] = {
+{
+ UA_TYPENAME("Key") /* .memberName */
+ &UA_TYPES[UA_TYPES_QUALIFIEDNAME], /* .memberType */
+ 0, /* .padding */
+ false, /* .isArray */
+ false /* .isOptional */
+},
+{
+ UA_TYPENAME("Value") /* .memberName */
+ &UA_TYPES[UA_TYPES_VARIANT], /* .memberType */
+ offsetof(UA_KeyValuePair, value) - offsetof(UA_KeyValuePair, key) - sizeof(UA_QualifiedName), /* .padding */
+ false, /* .isArray */
+ false /* .isOptional */
+},};
+
/* NodeClass */
#define NodeClass_members NULL
@@ -11030,199 +10154,176 @@ UA_calcSizeBinary(const void *p, const UA_DataType *type) {
static UA_DataTypeMember StructureField_members[7] = {
{
UA_TYPENAME("Name") /* .memberName */
- UA_TYPES_STRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STRING], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("Description") /* .memberName */
- UA_TYPES_LOCALIZEDTEXT, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
offsetof(UA_StructureField, description) - offsetof(UA_StructureField, name) - sizeof(UA_String), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("DataType") /* .memberName */
- UA_TYPES_NODEID, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
offsetof(UA_StructureField, dataType) - offsetof(UA_StructureField, description) - sizeof(UA_LocalizedText), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("ValueRank") /* .memberName */
- UA_TYPES_INT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_INT32], /* .memberType */
offsetof(UA_StructureField, valueRank) - offsetof(UA_StructureField, dataType) - sizeof(UA_NodeId), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("ArrayDimensions") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_StructureField, arrayDimensionsSize) - offsetof(UA_StructureField, valueRank) - sizeof(UA_Int32), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("MaxStringLength") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_StructureField, maxStringLength) - offsetof(UA_StructureField, arrayDimensions) - sizeof(void *), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("IsOptional") /* .memberName */
- UA_TYPES_BOOLEAN, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
offsetof(UA_StructureField, isOptional) - offsetof(UA_StructureField, maxStringLength) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* StructureDefinition */
static UA_DataTypeMember StructureDefinition_members[4] = {
{
UA_TYPENAME("DefaultEncodingId") /* .memberName */
- UA_TYPES_NODEID, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("BaseDataType") /* .memberName */
- UA_TYPES_NODEID, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
offsetof(UA_StructureDefinition, baseDataType) - offsetof(UA_StructureDefinition, defaultEncodingId) - sizeof(UA_NodeId), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("StructureType") /* .memberName */
- UA_TYPES_STRUCTURETYPE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STRUCTURETYPE], /* .memberType */
offsetof(UA_StructureDefinition, structureType) - offsetof(UA_StructureDefinition, baseDataType) - sizeof(UA_NodeId), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("Fields") /* .memberName */
- UA_TYPES_STRUCTUREFIELD, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STRUCTUREFIELD], /* .memberType */
offsetof(UA_StructureDefinition, fieldsSize) - offsetof(UA_StructureDefinition, structureType) - sizeof(UA_StructureType), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* Argument */
static UA_DataTypeMember Argument_members[5] = {
{
UA_TYPENAME("Name") /* .memberName */
- UA_TYPES_STRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STRING], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("DataType") /* .memberName */
- UA_TYPES_NODEID, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
offsetof(UA_Argument, dataType) - offsetof(UA_Argument, name) - sizeof(UA_String), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("ValueRank") /* .memberName */
- UA_TYPES_INT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_INT32], /* .memberType */
offsetof(UA_Argument, valueRank) - offsetof(UA_Argument, dataType) - sizeof(UA_NodeId), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("ArrayDimensions") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_Argument, arrayDimensionsSize) - offsetof(UA_Argument, valueRank) - sizeof(UA_Int32), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("Description") /* .memberName */
- UA_TYPES_LOCALIZEDTEXT, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
offsetof(UA_Argument, description) - offsetof(UA_Argument, arrayDimensions) - sizeof(void *), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* EnumValueType */
static UA_DataTypeMember EnumValueType_members[3] = {
{
UA_TYPENAME("Value") /* .memberName */
- UA_TYPES_INT64, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_INT64], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("DisplayName") /* .memberName */
- UA_TYPES_LOCALIZEDTEXT, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
offsetof(UA_EnumValueType, displayName) - offsetof(UA_EnumValueType, value) - sizeof(UA_Int64), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("Description") /* .memberName */
- UA_TYPES_LOCALIZEDTEXT, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
offsetof(UA_EnumValueType, description) - offsetof(UA_EnumValueType, displayName) - sizeof(UA_LocalizedText), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* EnumField */
static UA_DataTypeMember EnumField_members[4] = {
{
UA_TYPENAME("Value") /* .memberName */
- UA_TYPES_INT64, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_INT64], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("DisplayName") /* .memberName */
- UA_TYPES_LOCALIZEDTEXT, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
offsetof(UA_EnumField, displayName) - offsetof(UA_EnumField, value) - sizeof(UA_Int64), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("Description") /* .memberName */
- UA_TYPES_LOCALIZEDTEXT, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
offsetof(UA_EnumField, description) - offsetof(UA_EnumField, displayName) - sizeof(UA_LocalizedText), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("Name") /* .memberName */
- UA_TYPES_STRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STRING], /* .memberType */
offsetof(UA_EnumField, name) - offsetof(UA_EnumField, description) - sizeof(UA_LocalizedText), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* Duration */
@@ -11238,19 +10339,17 @@ static UA_DataTypeMember EnumField_members[4] = {
static UA_DataTypeMember TimeZoneDataType_members[2] = {
{
UA_TYPENAME("Offset") /* .memberName */
- UA_TYPES_INT16, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_INT16], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("DaylightSavingInOffset") /* .memberName */
- UA_TYPES_BOOLEAN, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
offsetof(UA_TimeZoneDataType, daylightSavingInOffset) - offsetof(UA_TimeZoneDataType, offset) - sizeof(UA_Int16), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* ApplicationType */
@@ -11260,234 +10359,207 @@ static UA_DataTypeMember TimeZoneDataType_members[2] = {
static UA_DataTypeMember ApplicationDescription_members[7] = {
{
UA_TYPENAME("ApplicationUri") /* .memberName */
- UA_TYPES_STRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STRING], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("ProductUri") /* .memberName */
- UA_TYPES_STRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STRING], /* .memberType */
offsetof(UA_ApplicationDescription, productUri) - offsetof(UA_ApplicationDescription, applicationUri) - sizeof(UA_String), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("ApplicationName") /* .memberName */
- UA_TYPES_LOCALIZEDTEXT, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
offsetof(UA_ApplicationDescription, applicationName) - offsetof(UA_ApplicationDescription, productUri) - sizeof(UA_String), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("ApplicationType") /* .memberName */
- UA_TYPES_APPLICATIONTYPE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_APPLICATIONTYPE], /* .memberType */
offsetof(UA_ApplicationDescription, applicationType) - offsetof(UA_ApplicationDescription, applicationName) - sizeof(UA_LocalizedText), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("GatewayServerUri") /* .memberName */
- UA_TYPES_STRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STRING], /* .memberType */
offsetof(UA_ApplicationDescription, gatewayServerUri) - offsetof(UA_ApplicationDescription, applicationType) - sizeof(UA_ApplicationType), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("DiscoveryProfileUri") /* .memberName */
- UA_TYPES_STRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STRING], /* .memberType */
offsetof(UA_ApplicationDescription, discoveryProfileUri) - offsetof(UA_ApplicationDescription, gatewayServerUri) - sizeof(UA_String), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("DiscoveryUrls") /* .memberName */
- UA_TYPES_STRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STRING], /* .memberType */
offsetof(UA_ApplicationDescription, discoveryUrlsSize) - offsetof(UA_ApplicationDescription, discoveryProfileUri) - sizeof(UA_String), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* RequestHeader */
static UA_DataTypeMember RequestHeader_members[7] = {
{
UA_TYPENAME("AuthenticationToken") /* .memberName */
- UA_TYPES_NODEID, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("Timestamp") /* .memberName */
- UA_TYPES_DATETIME, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */
offsetof(UA_RequestHeader, timestamp) - offsetof(UA_RequestHeader, authenticationToken) - sizeof(UA_NodeId), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("RequestHandle") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_RequestHeader, requestHandle) - offsetof(UA_RequestHeader, timestamp) - sizeof(UA_DateTime), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("ReturnDiagnostics") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_RequestHeader, returnDiagnostics) - offsetof(UA_RequestHeader, requestHandle) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("AuditEntryId") /* .memberName */
- UA_TYPES_STRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STRING], /* .memberType */
offsetof(UA_RequestHeader, auditEntryId) - offsetof(UA_RequestHeader, returnDiagnostics) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("TimeoutHint") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_RequestHeader, timeoutHint) - offsetof(UA_RequestHeader, auditEntryId) - sizeof(UA_String), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("AdditionalHeader") /* .memberName */
- UA_TYPES_EXTENSIONOBJECT, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], /* .memberType */
offsetof(UA_RequestHeader, additionalHeader) - offsetof(UA_RequestHeader, timeoutHint) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* ResponseHeader */
static UA_DataTypeMember ResponseHeader_members[6] = {
{
UA_TYPENAME("Timestamp") /* .memberName */
- UA_TYPES_DATETIME, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("RequestHandle") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_ResponseHeader, requestHandle) - offsetof(UA_ResponseHeader, timestamp) - sizeof(UA_DateTime), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("ServiceResult") /* .memberName */
- UA_TYPES_STATUSCODE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
offsetof(UA_ResponseHeader, serviceResult) - offsetof(UA_ResponseHeader, requestHandle) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("ServiceDiagnostics") /* .memberName */
- UA_TYPES_DIAGNOSTICINFO, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
offsetof(UA_ResponseHeader, serviceDiagnostics) - offsetof(UA_ResponseHeader, serviceResult) - sizeof(UA_StatusCode), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("StringTable") /* .memberName */
- UA_TYPES_STRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STRING], /* .memberType */
offsetof(UA_ResponseHeader, stringTableSize) - offsetof(UA_ResponseHeader, serviceDiagnostics) - sizeof(UA_DiagnosticInfo), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("AdditionalHeader") /* .memberName */
- UA_TYPES_EXTENSIONOBJECT, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], /* .memberType */
offsetof(UA_ResponseHeader, additionalHeader) - offsetof(UA_ResponseHeader, stringTable) - sizeof(void *), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* ServiceFault */
static UA_DataTypeMember ServiceFault_members[1] = {
{
UA_TYPENAME("ResponseHeader") /* .memberName */
- UA_TYPES_RESPONSEHEADER, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* FindServersRequest */
static UA_DataTypeMember FindServersRequest_members[4] = {
{
UA_TYPENAME("RequestHeader") /* .memberName */
- UA_TYPES_REQUESTHEADER, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("EndpointUrl") /* .memberName */
- UA_TYPES_STRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STRING], /* .memberType */
offsetof(UA_FindServersRequest, endpointUrl) - offsetof(UA_FindServersRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("LocaleIds") /* .memberName */
- UA_TYPES_STRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STRING], /* .memberType */
offsetof(UA_FindServersRequest, localeIdsSize) - offsetof(UA_FindServersRequest, endpointUrl) - sizeof(UA_String), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("ServerUris") /* .memberName */
- UA_TYPES_STRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STRING], /* .memberType */
offsetof(UA_FindServersRequest, serverUrisSize) - offsetof(UA_FindServersRequest, localeIds) - sizeof(void *), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* FindServersResponse */
static UA_DataTypeMember FindServersResponse_members[2] = {
{
UA_TYPENAME("ResponseHeader") /* .memberName */
- UA_TYPES_RESPONSEHEADER, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("Servers") /* .memberName */
- UA_TYPES_APPLICATIONDESCRIPTION, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_APPLICATIONDESCRIPTION], /* .memberType */
offsetof(UA_FindServersResponse, serversSize) - offsetof(UA_FindServersResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* MessageSecurityMode */
@@ -11500,164 +10572,145 @@ static UA_DataTypeMember FindServersResponse_members[2] = {
static UA_DataTypeMember UserTokenPolicy_members[5] = {
{
UA_TYPENAME("PolicyId") /* .memberName */
- UA_TYPES_STRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STRING], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("TokenType") /* .memberName */
- UA_TYPES_USERTOKENTYPE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_USERTOKENTYPE], /* .memberType */
offsetof(UA_UserTokenPolicy, tokenType) - offsetof(UA_UserTokenPolicy, policyId) - sizeof(UA_String), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("IssuedTokenType") /* .memberName */
- UA_TYPES_STRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STRING], /* .memberType */
offsetof(UA_UserTokenPolicy, issuedTokenType) - offsetof(UA_UserTokenPolicy, tokenType) - sizeof(UA_UserTokenType), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("IssuerEndpointUrl") /* .memberName */
- UA_TYPES_STRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STRING], /* .memberType */
offsetof(UA_UserTokenPolicy, issuerEndpointUrl) - offsetof(UA_UserTokenPolicy, issuedTokenType) - sizeof(UA_String), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("SecurityPolicyUri") /* .memberName */
- UA_TYPES_STRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STRING], /* .memberType */
offsetof(UA_UserTokenPolicy, securityPolicyUri) - offsetof(UA_UserTokenPolicy, issuerEndpointUrl) - sizeof(UA_String), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* EndpointDescription */
static UA_DataTypeMember EndpointDescription_members[8] = {
{
UA_TYPENAME("EndpointUrl") /* .memberName */
- UA_TYPES_STRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STRING], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("Server") /* .memberName */
- UA_TYPES_APPLICATIONDESCRIPTION, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_APPLICATIONDESCRIPTION], /* .memberType */
offsetof(UA_EndpointDescription, server) - offsetof(UA_EndpointDescription, endpointUrl) - sizeof(UA_String), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("ServerCertificate") /* .memberName */
- UA_TYPES_BYTESTRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */
offsetof(UA_EndpointDescription, serverCertificate) - offsetof(UA_EndpointDescription, server) - sizeof(UA_ApplicationDescription), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("SecurityMode") /* .memberName */
- UA_TYPES_MESSAGESECURITYMODE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_MESSAGESECURITYMODE], /* .memberType */
offsetof(UA_EndpointDescription, securityMode) - offsetof(UA_EndpointDescription, serverCertificate) - sizeof(UA_ByteString), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("SecurityPolicyUri") /* .memberName */
- UA_TYPES_STRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STRING], /* .memberType */
offsetof(UA_EndpointDescription, securityPolicyUri) - offsetof(UA_EndpointDescription, securityMode) - sizeof(UA_MessageSecurityMode), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("UserIdentityTokens") /* .memberName */
- UA_TYPES_USERTOKENPOLICY, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_USERTOKENPOLICY], /* .memberType */
offsetof(UA_EndpointDescription, userIdentityTokensSize) - offsetof(UA_EndpointDescription, securityPolicyUri) - sizeof(UA_String), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("TransportProfileUri") /* .memberName */
- UA_TYPES_STRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STRING], /* .memberType */
offsetof(UA_EndpointDescription, transportProfileUri) - offsetof(UA_EndpointDescription, userIdentityTokens) - sizeof(void *), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("SecurityLevel") /* .memberName */
- UA_TYPES_BYTE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_BYTE], /* .memberType */
offsetof(UA_EndpointDescription, securityLevel) - offsetof(UA_EndpointDescription, transportProfileUri) - sizeof(UA_String), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* GetEndpointsRequest */
static UA_DataTypeMember GetEndpointsRequest_members[4] = {
{
UA_TYPENAME("RequestHeader") /* .memberName */
- UA_TYPES_REQUESTHEADER, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("EndpointUrl") /* .memberName */
- UA_TYPES_STRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STRING], /* .memberType */
offsetof(UA_GetEndpointsRequest, endpointUrl) - offsetof(UA_GetEndpointsRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("LocaleIds") /* .memberName */
- UA_TYPES_STRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STRING], /* .memberType */
offsetof(UA_GetEndpointsRequest, localeIdsSize) - offsetof(UA_GetEndpointsRequest, endpointUrl) - sizeof(UA_String), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("ProfileUris") /* .memberName */
- UA_TYPES_STRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STRING], /* .memberType */
offsetof(UA_GetEndpointsRequest, profileUrisSize) - offsetof(UA_GetEndpointsRequest, localeIds) - sizeof(void *), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* GetEndpointsResponse */
static UA_DataTypeMember GetEndpointsResponse_members[2] = {
{
UA_TYPENAME("ResponseHeader") /* .memberName */
- UA_TYPES_RESPONSEHEADER, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("Endpoints") /* .memberName */
- UA_TYPES_ENDPOINTDESCRIPTION, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION], /* .memberType */
offsetof(UA_GetEndpointsResponse, endpointsSize) - offsetof(UA_GetEndpointsResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* SecurityTokenRequestType */
@@ -11667,558 +10720,495 @@ static UA_DataTypeMember GetEndpointsResponse_members[2] = {
static UA_DataTypeMember ChannelSecurityToken_members[4] = {
{
UA_TYPENAME("ChannelId") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("TokenId") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_ChannelSecurityToken, tokenId) - offsetof(UA_ChannelSecurityToken, channelId) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("CreatedAt") /* .memberName */
- UA_TYPES_DATETIME, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */
offsetof(UA_ChannelSecurityToken, createdAt) - offsetof(UA_ChannelSecurityToken, tokenId) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("RevisedLifetime") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_ChannelSecurityToken, revisedLifetime) - offsetof(UA_ChannelSecurityToken, createdAt) - sizeof(UA_DateTime), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* OpenSecureChannelRequest */
static UA_DataTypeMember OpenSecureChannelRequest_members[6] = {
{
UA_TYPENAME("RequestHeader") /* .memberName */
- UA_TYPES_REQUESTHEADER, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("ClientProtocolVersion") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_OpenSecureChannelRequest, clientProtocolVersion) - offsetof(UA_OpenSecureChannelRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("RequestType") /* .memberName */
- UA_TYPES_SECURITYTOKENREQUESTTYPE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_SECURITYTOKENREQUESTTYPE], /* .memberType */
offsetof(UA_OpenSecureChannelRequest, requestType) - offsetof(UA_OpenSecureChannelRequest, clientProtocolVersion) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("SecurityMode") /* .memberName */
- UA_TYPES_MESSAGESECURITYMODE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_MESSAGESECURITYMODE], /* .memberType */
offsetof(UA_OpenSecureChannelRequest, securityMode) - offsetof(UA_OpenSecureChannelRequest, requestType) - sizeof(UA_SecurityTokenRequestType), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("ClientNonce") /* .memberName */
- UA_TYPES_BYTESTRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */
offsetof(UA_OpenSecureChannelRequest, clientNonce) - offsetof(UA_OpenSecureChannelRequest, securityMode) - sizeof(UA_MessageSecurityMode), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("RequestedLifetime") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_OpenSecureChannelRequest, requestedLifetime) - offsetof(UA_OpenSecureChannelRequest, clientNonce) - sizeof(UA_ByteString), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* OpenSecureChannelResponse */
static UA_DataTypeMember OpenSecureChannelResponse_members[4] = {
{
UA_TYPENAME("ResponseHeader") /* .memberName */
- UA_TYPES_RESPONSEHEADER, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("ServerProtocolVersion") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_OpenSecureChannelResponse, serverProtocolVersion) - offsetof(UA_OpenSecureChannelResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("SecurityToken") /* .memberName */
- UA_TYPES_CHANNELSECURITYTOKEN, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_CHANNELSECURITYTOKEN], /* .memberType */
offsetof(UA_OpenSecureChannelResponse, securityToken) - offsetof(UA_OpenSecureChannelResponse, serverProtocolVersion) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("ServerNonce") /* .memberName */
- UA_TYPES_BYTESTRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */
offsetof(UA_OpenSecureChannelResponse, serverNonce) - offsetof(UA_OpenSecureChannelResponse, securityToken) - sizeof(UA_ChannelSecurityToken), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* CloseSecureChannelRequest */
static UA_DataTypeMember CloseSecureChannelRequest_members[1] = {
{
UA_TYPENAME("RequestHeader") /* .memberName */
- UA_TYPES_REQUESTHEADER, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* CloseSecureChannelResponse */
static UA_DataTypeMember CloseSecureChannelResponse_members[1] = {
{
UA_TYPENAME("ResponseHeader") /* .memberName */
- UA_TYPES_RESPONSEHEADER, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* SignedSoftwareCertificate */
static UA_DataTypeMember SignedSoftwareCertificate_members[2] = {
{
UA_TYPENAME("CertificateData") /* .memberName */
- UA_TYPES_BYTESTRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("Signature") /* .memberName */
- UA_TYPES_BYTESTRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */
offsetof(UA_SignedSoftwareCertificate, signature) - offsetof(UA_SignedSoftwareCertificate, certificateData) - sizeof(UA_ByteString), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* SignatureData */
static UA_DataTypeMember SignatureData_members[2] = {
{
UA_TYPENAME("Algorithm") /* .memberName */
- UA_TYPES_STRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STRING], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("Signature") /* .memberName */
- UA_TYPES_BYTESTRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */
offsetof(UA_SignatureData, signature) - offsetof(UA_SignatureData, algorithm) - sizeof(UA_String), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* CreateSessionRequest */
static UA_DataTypeMember CreateSessionRequest_members[9] = {
{
UA_TYPENAME("RequestHeader") /* .memberName */
- UA_TYPES_REQUESTHEADER, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("ClientDescription") /* .memberName */
- UA_TYPES_APPLICATIONDESCRIPTION, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_APPLICATIONDESCRIPTION], /* .memberType */
offsetof(UA_CreateSessionRequest, clientDescription) - offsetof(UA_CreateSessionRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("ServerUri") /* .memberName */
- UA_TYPES_STRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STRING], /* .memberType */
offsetof(UA_CreateSessionRequest, serverUri) - offsetof(UA_CreateSessionRequest, clientDescription) - sizeof(UA_ApplicationDescription), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("EndpointUrl") /* .memberName */
- UA_TYPES_STRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STRING], /* .memberType */
offsetof(UA_CreateSessionRequest, endpointUrl) - offsetof(UA_CreateSessionRequest, serverUri) - sizeof(UA_String), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("SessionName") /* .memberName */
- UA_TYPES_STRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STRING], /* .memberType */
offsetof(UA_CreateSessionRequest, sessionName) - offsetof(UA_CreateSessionRequest, endpointUrl) - sizeof(UA_String), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("ClientNonce") /* .memberName */
- UA_TYPES_BYTESTRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */
offsetof(UA_CreateSessionRequest, clientNonce) - offsetof(UA_CreateSessionRequest, sessionName) - sizeof(UA_String), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("ClientCertificate") /* .memberName */
- UA_TYPES_BYTESTRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */
offsetof(UA_CreateSessionRequest, clientCertificate) - offsetof(UA_CreateSessionRequest, clientNonce) - sizeof(UA_ByteString), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("RequestedSessionTimeout") /* .memberName */
- UA_TYPES_DOUBLE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */
offsetof(UA_CreateSessionRequest, requestedSessionTimeout) - offsetof(UA_CreateSessionRequest, clientCertificate) - sizeof(UA_ByteString), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("MaxResponseMessageSize") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_CreateSessionRequest, maxResponseMessageSize) - offsetof(UA_CreateSessionRequest, requestedSessionTimeout) - sizeof(UA_Double), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* CreateSessionResponse */
static UA_DataTypeMember CreateSessionResponse_members[10] = {
{
UA_TYPENAME("ResponseHeader") /* .memberName */
- UA_TYPES_RESPONSEHEADER, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("SessionId") /* .memberName */
- UA_TYPES_NODEID, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
offsetof(UA_CreateSessionResponse, sessionId) - offsetof(UA_CreateSessionResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("AuthenticationToken") /* .memberName */
- UA_TYPES_NODEID, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
offsetof(UA_CreateSessionResponse, authenticationToken) - offsetof(UA_CreateSessionResponse, sessionId) - sizeof(UA_NodeId), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("RevisedSessionTimeout") /* .memberName */
- UA_TYPES_DOUBLE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */
offsetof(UA_CreateSessionResponse, revisedSessionTimeout) - offsetof(UA_CreateSessionResponse, authenticationToken) - sizeof(UA_NodeId), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("ServerNonce") /* .memberName */
- UA_TYPES_BYTESTRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */
offsetof(UA_CreateSessionResponse, serverNonce) - offsetof(UA_CreateSessionResponse, revisedSessionTimeout) - sizeof(UA_Double), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("ServerCertificate") /* .memberName */
- UA_TYPES_BYTESTRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */
offsetof(UA_CreateSessionResponse, serverCertificate) - offsetof(UA_CreateSessionResponse, serverNonce) - sizeof(UA_ByteString), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("ServerEndpoints") /* .memberName */
- UA_TYPES_ENDPOINTDESCRIPTION, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION], /* .memberType */
offsetof(UA_CreateSessionResponse, serverEndpointsSize) - offsetof(UA_CreateSessionResponse, serverCertificate) - sizeof(UA_ByteString), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("ServerSoftwareCertificates") /* .memberName */
- UA_TYPES_SIGNEDSOFTWARECERTIFICATE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_SIGNEDSOFTWARECERTIFICATE], /* .memberType */
offsetof(UA_CreateSessionResponse, serverSoftwareCertificatesSize) - offsetof(UA_CreateSessionResponse, serverEndpoints) - sizeof(void *), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("ServerSignature") /* .memberName */
- UA_TYPES_SIGNATUREDATA, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_SIGNATUREDATA], /* .memberType */
offsetof(UA_CreateSessionResponse, serverSignature) - offsetof(UA_CreateSessionResponse, serverSoftwareCertificates) - sizeof(void *), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("MaxRequestMessageSize") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_CreateSessionResponse, maxRequestMessageSize) - offsetof(UA_CreateSessionResponse, serverSignature) - sizeof(UA_SignatureData), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* UserIdentityToken */
static UA_DataTypeMember UserIdentityToken_members[1] = {
{
UA_TYPENAME("PolicyId") /* .memberName */
- UA_TYPES_STRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STRING], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* AnonymousIdentityToken */
static UA_DataTypeMember AnonymousIdentityToken_members[1] = {
{
UA_TYPENAME("PolicyId") /* .memberName */
- UA_TYPES_STRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STRING], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* UserNameIdentityToken */
static UA_DataTypeMember UserNameIdentityToken_members[4] = {
{
UA_TYPENAME("PolicyId") /* .memberName */
- UA_TYPES_STRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STRING], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("UserName") /* .memberName */
- UA_TYPES_STRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STRING], /* .memberType */
offsetof(UA_UserNameIdentityToken, userName) - offsetof(UA_UserNameIdentityToken, policyId) - sizeof(UA_String), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("Password") /* .memberName */
- UA_TYPES_BYTESTRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */
offsetof(UA_UserNameIdentityToken, password) - offsetof(UA_UserNameIdentityToken, userName) - sizeof(UA_String), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("EncryptionAlgorithm") /* .memberName */
- UA_TYPES_STRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STRING], /* .memberType */
offsetof(UA_UserNameIdentityToken, encryptionAlgorithm) - offsetof(UA_UserNameIdentityToken, password) - sizeof(UA_ByteString), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* X509IdentityToken */
static UA_DataTypeMember X509IdentityToken_members[2] = {
{
UA_TYPENAME("PolicyId") /* .memberName */
- UA_TYPES_STRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STRING], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("CertificateData") /* .memberName */
- UA_TYPES_BYTESTRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */
offsetof(UA_X509IdentityToken, certificateData) - offsetof(UA_X509IdentityToken, policyId) - sizeof(UA_String), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* IssuedIdentityToken */
static UA_DataTypeMember IssuedIdentityToken_members[3] = {
{
UA_TYPENAME("PolicyId") /* .memberName */
- UA_TYPES_STRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STRING], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("TokenData") /* .memberName */
- UA_TYPES_BYTESTRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */
offsetof(UA_IssuedIdentityToken, tokenData) - offsetof(UA_IssuedIdentityToken, policyId) - sizeof(UA_String), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("EncryptionAlgorithm") /* .memberName */
- UA_TYPES_STRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STRING], /* .memberType */
offsetof(UA_IssuedIdentityToken, encryptionAlgorithm) - offsetof(UA_IssuedIdentityToken, tokenData) - sizeof(UA_ByteString), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* ActivateSessionRequest */
static UA_DataTypeMember ActivateSessionRequest_members[6] = {
{
UA_TYPENAME("RequestHeader") /* .memberName */
- UA_TYPES_REQUESTHEADER, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("ClientSignature") /* .memberName */
- UA_TYPES_SIGNATUREDATA, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_SIGNATUREDATA], /* .memberType */
offsetof(UA_ActivateSessionRequest, clientSignature) - offsetof(UA_ActivateSessionRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("ClientSoftwareCertificates") /* .memberName */
- UA_TYPES_SIGNEDSOFTWARECERTIFICATE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_SIGNEDSOFTWARECERTIFICATE], /* .memberType */
offsetof(UA_ActivateSessionRequest, clientSoftwareCertificatesSize) - offsetof(UA_ActivateSessionRequest, clientSignature) - sizeof(UA_SignatureData), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("LocaleIds") /* .memberName */
- UA_TYPES_STRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STRING], /* .memberType */
offsetof(UA_ActivateSessionRequest, localeIdsSize) - offsetof(UA_ActivateSessionRequest, clientSoftwareCertificates) - sizeof(void *), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("UserIdentityToken") /* .memberName */
- UA_TYPES_EXTENSIONOBJECT, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], /* .memberType */
offsetof(UA_ActivateSessionRequest, userIdentityToken) - offsetof(UA_ActivateSessionRequest, localeIds) - sizeof(void *), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("UserTokenSignature") /* .memberName */
- UA_TYPES_SIGNATUREDATA, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_SIGNATUREDATA], /* .memberType */
offsetof(UA_ActivateSessionRequest, userTokenSignature) - offsetof(UA_ActivateSessionRequest, userIdentityToken) - sizeof(UA_ExtensionObject), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* ActivateSessionResponse */
static UA_DataTypeMember ActivateSessionResponse_members[4] = {
{
UA_TYPENAME("ResponseHeader") /* .memberName */
- UA_TYPES_RESPONSEHEADER, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("ServerNonce") /* .memberName */
- UA_TYPES_BYTESTRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */
offsetof(UA_ActivateSessionResponse, serverNonce) - offsetof(UA_ActivateSessionResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("Results") /* .memberName */
- UA_TYPES_STATUSCODE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
offsetof(UA_ActivateSessionResponse, resultsSize) - offsetof(UA_ActivateSessionResponse, serverNonce) - sizeof(UA_ByteString), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("DiagnosticInfos") /* .memberName */
- UA_TYPES_DIAGNOSTICINFO, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
offsetof(UA_ActivateSessionResponse, diagnosticInfosSize) - offsetof(UA_ActivateSessionResponse, results) - sizeof(void *), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* CloseSessionRequest */
static UA_DataTypeMember CloseSessionRequest_members[2] = {
{
UA_TYPENAME("RequestHeader") /* .memberName */
- UA_TYPES_REQUESTHEADER, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("DeleteSubscriptions") /* .memberName */
- UA_TYPES_BOOLEAN, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
offsetof(UA_CloseSessionRequest, deleteSubscriptions) - offsetof(UA_CloseSessionRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* CloseSessionResponse */
static UA_DataTypeMember CloseSessionResponse_members[1] = {
{
UA_TYPENAME("ResponseHeader") /* .memberName */
- UA_TYPES_RESPONSEHEADER, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* NodeAttributesMask */
@@ -12228,946 +11218,836 @@ static UA_DataTypeMember CloseSessionResponse_members[1] = {
static UA_DataTypeMember NodeAttributes_members[5] = {
{
UA_TYPENAME("SpecifiedAttributes") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("DisplayName") /* .memberName */
- UA_TYPES_LOCALIZEDTEXT, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
offsetof(UA_NodeAttributes, displayName) - offsetof(UA_NodeAttributes, specifiedAttributes) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("Description") /* .memberName */
- UA_TYPES_LOCALIZEDTEXT, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
offsetof(UA_NodeAttributes, description) - offsetof(UA_NodeAttributes, displayName) - sizeof(UA_LocalizedText), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("WriteMask") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_NodeAttributes, writeMask) - offsetof(UA_NodeAttributes, description) - sizeof(UA_LocalizedText), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("UserWriteMask") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_NodeAttributes, userWriteMask) - offsetof(UA_NodeAttributes, writeMask) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* ObjectAttributes */
static UA_DataTypeMember ObjectAttributes_members[6] = {
{
UA_TYPENAME("SpecifiedAttributes") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("DisplayName") /* .memberName */
- UA_TYPES_LOCALIZEDTEXT, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
offsetof(UA_ObjectAttributes, displayName) - offsetof(UA_ObjectAttributes, specifiedAttributes) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("Description") /* .memberName */
- UA_TYPES_LOCALIZEDTEXT, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
offsetof(UA_ObjectAttributes, description) - offsetof(UA_ObjectAttributes, displayName) - sizeof(UA_LocalizedText), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("WriteMask") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_ObjectAttributes, writeMask) - offsetof(UA_ObjectAttributes, description) - sizeof(UA_LocalizedText), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("UserWriteMask") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_ObjectAttributes, userWriteMask) - offsetof(UA_ObjectAttributes, writeMask) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("EventNotifier") /* .memberName */
- UA_TYPES_BYTE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_BYTE], /* .memberType */
offsetof(UA_ObjectAttributes, eventNotifier) - offsetof(UA_ObjectAttributes, userWriteMask) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* VariableAttributes */
static UA_DataTypeMember VariableAttributes_members[13] = {
{
UA_TYPENAME("SpecifiedAttributes") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("DisplayName") /* .memberName */
- UA_TYPES_LOCALIZEDTEXT, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
offsetof(UA_VariableAttributes, displayName) - offsetof(UA_VariableAttributes, specifiedAttributes) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("Description") /* .memberName */
- UA_TYPES_LOCALIZEDTEXT, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
offsetof(UA_VariableAttributes, description) - offsetof(UA_VariableAttributes, displayName) - sizeof(UA_LocalizedText), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("WriteMask") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_VariableAttributes, writeMask) - offsetof(UA_VariableAttributes, description) - sizeof(UA_LocalizedText), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("UserWriteMask") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_VariableAttributes, userWriteMask) - offsetof(UA_VariableAttributes, writeMask) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("Value") /* .memberName */
- UA_TYPES_VARIANT, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_VARIANT], /* .memberType */
offsetof(UA_VariableAttributes, value) - offsetof(UA_VariableAttributes, userWriteMask) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("DataType") /* .memberName */
- UA_TYPES_NODEID, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
offsetof(UA_VariableAttributes, dataType) - offsetof(UA_VariableAttributes, value) - sizeof(UA_Variant), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("ValueRank") /* .memberName */
- UA_TYPES_INT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_INT32], /* .memberType */
offsetof(UA_VariableAttributes, valueRank) - offsetof(UA_VariableAttributes, dataType) - sizeof(UA_NodeId), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("ArrayDimensions") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_VariableAttributes, arrayDimensionsSize) - offsetof(UA_VariableAttributes, valueRank) - sizeof(UA_Int32), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("AccessLevel") /* .memberName */
- UA_TYPES_BYTE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_BYTE], /* .memberType */
offsetof(UA_VariableAttributes, accessLevel) - offsetof(UA_VariableAttributes, arrayDimensions) - sizeof(void *), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("UserAccessLevel") /* .memberName */
- UA_TYPES_BYTE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_BYTE], /* .memberType */
offsetof(UA_VariableAttributes, userAccessLevel) - offsetof(UA_VariableAttributes, accessLevel) - sizeof(UA_Byte), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("MinimumSamplingInterval") /* .memberName */
- UA_TYPES_DOUBLE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */
offsetof(UA_VariableAttributes, minimumSamplingInterval) - offsetof(UA_VariableAttributes, userAccessLevel) - sizeof(UA_Byte), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("Historizing") /* .memberName */
- UA_TYPES_BOOLEAN, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
offsetof(UA_VariableAttributes, historizing) - offsetof(UA_VariableAttributes, minimumSamplingInterval) - sizeof(UA_Double), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* MethodAttributes */
static UA_DataTypeMember MethodAttributes_members[7] = {
{
UA_TYPENAME("SpecifiedAttributes") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("DisplayName") /* .memberName */
- UA_TYPES_LOCALIZEDTEXT, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
offsetof(UA_MethodAttributes, displayName) - offsetof(UA_MethodAttributes, specifiedAttributes) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("Description") /* .memberName */
- UA_TYPES_LOCALIZEDTEXT, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
offsetof(UA_MethodAttributes, description) - offsetof(UA_MethodAttributes, displayName) - sizeof(UA_LocalizedText), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("WriteMask") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_MethodAttributes, writeMask) - offsetof(UA_MethodAttributes, description) - sizeof(UA_LocalizedText), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("UserWriteMask") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_MethodAttributes, userWriteMask) - offsetof(UA_MethodAttributes, writeMask) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("Executable") /* .memberName */
- UA_TYPES_BOOLEAN, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
offsetof(UA_MethodAttributes, executable) - offsetof(UA_MethodAttributes, userWriteMask) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("UserExecutable") /* .memberName */
- UA_TYPES_BOOLEAN, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
offsetof(UA_MethodAttributes, userExecutable) - offsetof(UA_MethodAttributes, executable) - sizeof(UA_Boolean), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* ObjectTypeAttributes */
static UA_DataTypeMember ObjectTypeAttributes_members[6] = {
{
UA_TYPENAME("SpecifiedAttributes") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("DisplayName") /* .memberName */
- UA_TYPES_LOCALIZEDTEXT, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
offsetof(UA_ObjectTypeAttributes, displayName) - offsetof(UA_ObjectTypeAttributes, specifiedAttributes) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("Description") /* .memberName */
- UA_TYPES_LOCALIZEDTEXT, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
offsetof(UA_ObjectTypeAttributes, description) - offsetof(UA_ObjectTypeAttributes, displayName) - sizeof(UA_LocalizedText), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("WriteMask") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_ObjectTypeAttributes, writeMask) - offsetof(UA_ObjectTypeAttributes, description) - sizeof(UA_LocalizedText), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("UserWriteMask") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_ObjectTypeAttributes, userWriteMask) - offsetof(UA_ObjectTypeAttributes, writeMask) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("IsAbstract") /* .memberName */
- UA_TYPES_BOOLEAN, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
offsetof(UA_ObjectTypeAttributes, isAbstract) - offsetof(UA_ObjectTypeAttributes, userWriteMask) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* VariableTypeAttributes */
static UA_DataTypeMember VariableTypeAttributes_members[10] = {
{
UA_TYPENAME("SpecifiedAttributes") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("DisplayName") /* .memberName */
- UA_TYPES_LOCALIZEDTEXT, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
offsetof(UA_VariableTypeAttributes, displayName) - offsetof(UA_VariableTypeAttributes, specifiedAttributes) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("Description") /* .memberName */
- UA_TYPES_LOCALIZEDTEXT, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
offsetof(UA_VariableTypeAttributes, description) - offsetof(UA_VariableTypeAttributes, displayName) - sizeof(UA_LocalizedText), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("WriteMask") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_VariableTypeAttributes, writeMask) - offsetof(UA_VariableTypeAttributes, description) - sizeof(UA_LocalizedText), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("UserWriteMask") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_VariableTypeAttributes, userWriteMask) - offsetof(UA_VariableTypeAttributes, writeMask) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("Value") /* .memberName */
- UA_TYPES_VARIANT, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_VARIANT], /* .memberType */
offsetof(UA_VariableTypeAttributes, value) - offsetof(UA_VariableTypeAttributes, userWriteMask) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("DataType") /* .memberName */
- UA_TYPES_NODEID, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
offsetof(UA_VariableTypeAttributes, dataType) - offsetof(UA_VariableTypeAttributes, value) - sizeof(UA_Variant), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("ValueRank") /* .memberName */
- UA_TYPES_INT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_INT32], /* .memberType */
offsetof(UA_VariableTypeAttributes, valueRank) - offsetof(UA_VariableTypeAttributes, dataType) - sizeof(UA_NodeId), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("ArrayDimensions") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_VariableTypeAttributes, arrayDimensionsSize) - offsetof(UA_VariableTypeAttributes, valueRank) - sizeof(UA_Int32), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("IsAbstract") /* .memberName */
- UA_TYPES_BOOLEAN, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
offsetof(UA_VariableTypeAttributes, isAbstract) - offsetof(UA_VariableTypeAttributes, arrayDimensions) - sizeof(void *), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* ReferenceTypeAttributes */
static UA_DataTypeMember ReferenceTypeAttributes_members[8] = {
{
UA_TYPENAME("SpecifiedAttributes") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("DisplayName") /* .memberName */
- UA_TYPES_LOCALIZEDTEXT, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
offsetof(UA_ReferenceTypeAttributes, displayName) - offsetof(UA_ReferenceTypeAttributes, specifiedAttributes) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("Description") /* .memberName */
- UA_TYPES_LOCALIZEDTEXT, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
offsetof(UA_ReferenceTypeAttributes, description) - offsetof(UA_ReferenceTypeAttributes, displayName) - sizeof(UA_LocalizedText), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("WriteMask") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_ReferenceTypeAttributes, writeMask) - offsetof(UA_ReferenceTypeAttributes, description) - sizeof(UA_LocalizedText), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("UserWriteMask") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_ReferenceTypeAttributes, userWriteMask) - offsetof(UA_ReferenceTypeAttributes, writeMask) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("IsAbstract") /* .memberName */
- UA_TYPES_BOOLEAN, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
offsetof(UA_ReferenceTypeAttributes, isAbstract) - offsetof(UA_ReferenceTypeAttributes, userWriteMask) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("Symmetric") /* .memberName */
- UA_TYPES_BOOLEAN, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
offsetof(UA_ReferenceTypeAttributes, symmetric) - offsetof(UA_ReferenceTypeAttributes, isAbstract) - sizeof(UA_Boolean), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("InverseName") /* .memberName */
- UA_TYPES_LOCALIZEDTEXT, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
offsetof(UA_ReferenceTypeAttributes, inverseName) - offsetof(UA_ReferenceTypeAttributes, symmetric) - sizeof(UA_Boolean), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* DataTypeAttributes */
static UA_DataTypeMember DataTypeAttributes_members[6] = {
{
UA_TYPENAME("SpecifiedAttributes") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("DisplayName") /* .memberName */
- UA_TYPES_LOCALIZEDTEXT, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
offsetof(UA_DataTypeAttributes, displayName) - offsetof(UA_DataTypeAttributes, specifiedAttributes) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("Description") /* .memberName */
- UA_TYPES_LOCALIZEDTEXT, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
offsetof(UA_DataTypeAttributes, description) - offsetof(UA_DataTypeAttributes, displayName) - sizeof(UA_LocalizedText), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("WriteMask") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_DataTypeAttributes, writeMask) - offsetof(UA_DataTypeAttributes, description) - sizeof(UA_LocalizedText), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("UserWriteMask") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_DataTypeAttributes, userWriteMask) - offsetof(UA_DataTypeAttributes, writeMask) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("IsAbstract") /* .memberName */
- UA_TYPES_BOOLEAN, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
offsetof(UA_DataTypeAttributes, isAbstract) - offsetof(UA_DataTypeAttributes, userWriteMask) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* ViewAttributes */
static UA_DataTypeMember ViewAttributes_members[7] = {
{
UA_TYPENAME("SpecifiedAttributes") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("DisplayName") /* .memberName */
- UA_TYPES_LOCALIZEDTEXT, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
offsetof(UA_ViewAttributes, displayName) - offsetof(UA_ViewAttributes, specifiedAttributes) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("Description") /* .memberName */
- UA_TYPES_LOCALIZEDTEXT, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
offsetof(UA_ViewAttributes, description) - offsetof(UA_ViewAttributes, displayName) - sizeof(UA_LocalizedText), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("WriteMask") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_ViewAttributes, writeMask) - offsetof(UA_ViewAttributes, description) - sizeof(UA_LocalizedText), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("UserWriteMask") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_ViewAttributes, userWriteMask) - offsetof(UA_ViewAttributes, writeMask) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("ContainsNoLoops") /* .memberName */
- UA_TYPES_BOOLEAN, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
offsetof(UA_ViewAttributes, containsNoLoops) - offsetof(UA_ViewAttributes, userWriteMask) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("EventNotifier") /* .memberName */
- UA_TYPES_BYTE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_BYTE], /* .memberType */
offsetof(UA_ViewAttributes, eventNotifier) - offsetof(UA_ViewAttributes, containsNoLoops) - sizeof(UA_Boolean), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* AddNodesItem */
static UA_DataTypeMember AddNodesItem_members[7] = {
{
UA_TYPENAME("ParentNodeId") /* .memberName */
- UA_TYPES_EXPANDEDNODEID, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_EXPANDEDNODEID], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("ReferenceTypeId") /* .memberName */
- UA_TYPES_NODEID, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
offsetof(UA_AddNodesItem, referenceTypeId) - offsetof(UA_AddNodesItem, parentNodeId) - sizeof(UA_ExpandedNodeId), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("RequestedNewNodeId") /* .memberName */
- UA_TYPES_EXPANDEDNODEID, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_EXPANDEDNODEID], /* .memberType */
offsetof(UA_AddNodesItem, requestedNewNodeId) - offsetof(UA_AddNodesItem, referenceTypeId) - sizeof(UA_NodeId), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("BrowseName") /* .memberName */
- UA_TYPES_QUALIFIEDNAME, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_QUALIFIEDNAME], /* .memberType */
offsetof(UA_AddNodesItem, browseName) - offsetof(UA_AddNodesItem, requestedNewNodeId) - sizeof(UA_ExpandedNodeId), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("NodeClass") /* .memberName */
- UA_TYPES_NODECLASS, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_NODECLASS], /* .memberType */
offsetof(UA_AddNodesItem, nodeClass) - offsetof(UA_AddNodesItem, browseName) - sizeof(UA_QualifiedName), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("NodeAttributes") /* .memberName */
- UA_TYPES_EXTENSIONOBJECT, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], /* .memberType */
offsetof(UA_AddNodesItem, nodeAttributes) - offsetof(UA_AddNodesItem, nodeClass) - sizeof(UA_NodeClass), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("TypeDefinition") /* .memberName */
- UA_TYPES_EXPANDEDNODEID, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_EXPANDEDNODEID], /* .memberType */
offsetof(UA_AddNodesItem, typeDefinition) - offsetof(UA_AddNodesItem, nodeAttributes) - sizeof(UA_ExtensionObject), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* AddNodesResult */
static UA_DataTypeMember AddNodesResult_members[2] = {
{
UA_TYPENAME("StatusCode") /* .memberName */
- UA_TYPES_STATUSCODE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("AddedNodeId") /* .memberName */
- UA_TYPES_NODEID, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
offsetof(UA_AddNodesResult, addedNodeId) - offsetof(UA_AddNodesResult, statusCode) - sizeof(UA_StatusCode), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* AddNodesRequest */
static UA_DataTypeMember AddNodesRequest_members[2] = {
{
UA_TYPENAME("RequestHeader") /* .memberName */
- UA_TYPES_REQUESTHEADER, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("NodesToAdd") /* .memberName */
- UA_TYPES_ADDNODESITEM, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_ADDNODESITEM], /* .memberType */
offsetof(UA_AddNodesRequest, nodesToAddSize) - offsetof(UA_AddNodesRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* AddNodesResponse */
static UA_DataTypeMember AddNodesResponse_members[3] = {
{
UA_TYPENAME("ResponseHeader") /* .memberName */
- UA_TYPES_RESPONSEHEADER, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("Results") /* .memberName */
- UA_TYPES_ADDNODESRESULT, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_ADDNODESRESULT], /* .memberType */
offsetof(UA_AddNodesResponse, resultsSize) - offsetof(UA_AddNodesResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("DiagnosticInfos") /* .memberName */
- UA_TYPES_DIAGNOSTICINFO, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
offsetof(UA_AddNodesResponse, diagnosticInfosSize) - offsetof(UA_AddNodesResponse, results) - sizeof(void *), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* AddReferencesItem */
static UA_DataTypeMember AddReferencesItem_members[6] = {
{
UA_TYPENAME("SourceNodeId") /* .memberName */
- UA_TYPES_NODEID, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("ReferenceTypeId") /* .memberName */
- UA_TYPES_NODEID, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
offsetof(UA_AddReferencesItem, referenceTypeId) - offsetof(UA_AddReferencesItem, sourceNodeId) - sizeof(UA_NodeId), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("IsForward") /* .memberName */
- UA_TYPES_BOOLEAN, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
offsetof(UA_AddReferencesItem, isForward) - offsetof(UA_AddReferencesItem, referenceTypeId) - sizeof(UA_NodeId), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("TargetServerUri") /* .memberName */
- UA_TYPES_STRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STRING], /* .memberType */
offsetof(UA_AddReferencesItem, targetServerUri) - offsetof(UA_AddReferencesItem, isForward) - sizeof(UA_Boolean), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("TargetNodeId") /* .memberName */
- UA_TYPES_EXPANDEDNODEID, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_EXPANDEDNODEID], /* .memberType */
offsetof(UA_AddReferencesItem, targetNodeId) - offsetof(UA_AddReferencesItem, targetServerUri) - sizeof(UA_String), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("TargetNodeClass") /* .memberName */
- UA_TYPES_NODECLASS, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_NODECLASS], /* .memberType */
offsetof(UA_AddReferencesItem, targetNodeClass) - offsetof(UA_AddReferencesItem, targetNodeId) - sizeof(UA_ExpandedNodeId), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* AddReferencesRequest */
static UA_DataTypeMember AddReferencesRequest_members[2] = {
{
UA_TYPENAME("RequestHeader") /* .memberName */
- UA_TYPES_REQUESTHEADER, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("ReferencesToAdd") /* .memberName */
- UA_TYPES_ADDREFERENCESITEM, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_ADDREFERENCESITEM], /* .memberType */
offsetof(UA_AddReferencesRequest, referencesToAddSize) - offsetof(UA_AddReferencesRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* AddReferencesResponse */
static UA_DataTypeMember AddReferencesResponse_members[3] = {
{
UA_TYPENAME("ResponseHeader") /* .memberName */
- UA_TYPES_RESPONSEHEADER, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("Results") /* .memberName */
- UA_TYPES_STATUSCODE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
offsetof(UA_AddReferencesResponse, resultsSize) - offsetof(UA_AddReferencesResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("DiagnosticInfos") /* .memberName */
- UA_TYPES_DIAGNOSTICINFO, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
offsetof(UA_AddReferencesResponse, diagnosticInfosSize) - offsetof(UA_AddReferencesResponse, results) - sizeof(void *), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* DeleteNodesItem */
static UA_DataTypeMember DeleteNodesItem_members[2] = {
{
UA_TYPENAME("NodeId") /* .memberName */
- UA_TYPES_NODEID, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("DeleteTargetReferences") /* .memberName */
- UA_TYPES_BOOLEAN, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
offsetof(UA_DeleteNodesItem, deleteTargetReferences) - offsetof(UA_DeleteNodesItem, nodeId) - sizeof(UA_NodeId), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* DeleteNodesRequest */
static UA_DataTypeMember DeleteNodesRequest_members[2] = {
{
UA_TYPENAME("RequestHeader") /* .memberName */
- UA_TYPES_REQUESTHEADER, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("NodesToDelete") /* .memberName */
- UA_TYPES_DELETENODESITEM, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DELETENODESITEM], /* .memberType */
offsetof(UA_DeleteNodesRequest, nodesToDeleteSize) - offsetof(UA_DeleteNodesRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* DeleteNodesResponse */
static UA_DataTypeMember DeleteNodesResponse_members[3] = {
{
UA_TYPENAME("ResponseHeader") /* .memberName */
- UA_TYPES_RESPONSEHEADER, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("Results") /* .memberName */
- UA_TYPES_STATUSCODE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
offsetof(UA_DeleteNodesResponse, resultsSize) - offsetof(UA_DeleteNodesResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("DiagnosticInfos") /* .memberName */
- UA_TYPES_DIAGNOSTICINFO, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
offsetof(UA_DeleteNodesResponse, diagnosticInfosSize) - offsetof(UA_DeleteNodesResponse, results) - sizeof(void *), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* DeleteReferencesItem */
static UA_DataTypeMember DeleteReferencesItem_members[5] = {
{
UA_TYPENAME("SourceNodeId") /* .memberName */
- UA_TYPES_NODEID, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("ReferenceTypeId") /* .memberName */
- UA_TYPES_NODEID, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
offsetof(UA_DeleteReferencesItem, referenceTypeId) - offsetof(UA_DeleteReferencesItem, sourceNodeId) - sizeof(UA_NodeId), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("IsForward") /* .memberName */
- UA_TYPES_BOOLEAN, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
offsetof(UA_DeleteReferencesItem, isForward) - offsetof(UA_DeleteReferencesItem, referenceTypeId) - sizeof(UA_NodeId), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("TargetNodeId") /* .memberName */
- UA_TYPES_EXPANDEDNODEID, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_EXPANDEDNODEID], /* .memberType */
offsetof(UA_DeleteReferencesItem, targetNodeId) - offsetof(UA_DeleteReferencesItem, isForward) - sizeof(UA_Boolean), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("DeleteBidirectional") /* .memberName */
- UA_TYPES_BOOLEAN, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
offsetof(UA_DeleteReferencesItem, deleteBidirectional) - offsetof(UA_DeleteReferencesItem, targetNodeId) - sizeof(UA_ExpandedNodeId), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* DeleteReferencesRequest */
static UA_DataTypeMember DeleteReferencesRequest_members[2] = {
{
UA_TYPENAME("RequestHeader") /* .memberName */
- UA_TYPES_REQUESTHEADER, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("ReferencesToDelete") /* .memberName */
- UA_TYPES_DELETEREFERENCESITEM, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DELETEREFERENCESITEM], /* .memberType */
offsetof(UA_DeleteReferencesRequest, referencesToDeleteSize) - offsetof(UA_DeleteReferencesRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* DeleteReferencesResponse */
static UA_DataTypeMember DeleteReferencesResponse_members[3] = {
{
UA_TYPENAME("ResponseHeader") /* .memberName */
- UA_TYPES_RESPONSEHEADER, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("Results") /* .memberName */
- UA_TYPES_STATUSCODE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
offsetof(UA_DeleteReferencesResponse, resultsSize) - offsetof(UA_DeleteReferencesResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("DiagnosticInfos") /* .memberName */
- UA_TYPES_DIAGNOSTICINFO, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
offsetof(UA_DeleteReferencesResponse, diagnosticInfosSize) - offsetof(UA_DeleteReferencesResponse, results) - sizeof(void *), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* BrowseDirection */
@@ -13177,78 +12057,69 @@ static UA_DataTypeMember DeleteReferencesResponse_members[3] = {
static UA_DataTypeMember ViewDescription_members[3] = {
{
UA_TYPENAME("ViewId") /* .memberName */
- UA_TYPES_NODEID, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("Timestamp") /* .memberName */
- UA_TYPES_DATETIME, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */
offsetof(UA_ViewDescription, timestamp) - offsetof(UA_ViewDescription, viewId) - sizeof(UA_NodeId), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("ViewVersion") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_ViewDescription, viewVersion) - offsetof(UA_ViewDescription, timestamp) - sizeof(UA_DateTime), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* BrowseDescription */
static UA_DataTypeMember BrowseDescription_members[6] = {
{
UA_TYPENAME("NodeId") /* .memberName */
- UA_TYPES_NODEID, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("BrowseDirection") /* .memberName */
- UA_TYPES_BROWSEDIRECTION, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_BROWSEDIRECTION], /* .memberType */
offsetof(UA_BrowseDescription, browseDirection) - offsetof(UA_BrowseDescription, nodeId) - sizeof(UA_NodeId), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("ReferenceTypeId") /* .memberName */
- UA_TYPES_NODEID, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
offsetof(UA_BrowseDescription, referenceTypeId) - offsetof(UA_BrowseDescription, browseDirection) - sizeof(UA_BrowseDirection), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("IncludeSubtypes") /* .memberName */
- UA_TYPES_BOOLEAN, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
offsetof(UA_BrowseDescription, includeSubtypes) - offsetof(UA_BrowseDescription, referenceTypeId) - sizeof(UA_NodeId), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("NodeClassMask") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_BrowseDescription, nodeClassMask) - offsetof(UA_BrowseDescription, includeSubtypes) - sizeof(UA_Boolean), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("ResultMask") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_BrowseDescription, resultMask) - offsetof(UA_BrowseDescription, nodeClassMask) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* BrowseResultMask */
@@ -13258,419 +12129,373 @@ static UA_DataTypeMember BrowseDescription_members[6] = {
static UA_DataTypeMember ReferenceDescription_members[7] = {
{
UA_TYPENAME("ReferenceTypeId") /* .memberName */
- UA_TYPES_NODEID, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("IsForward") /* .memberName */
- UA_TYPES_BOOLEAN, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
offsetof(UA_ReferenceDescription, isForward) - offsetof(UA_ReferenceDescription, referenceTypeId) - sizeof(UA_NodeId), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("NodeId") /* .memberName */
- UA_TYPES_EXPANDEDNODEID, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_EXPANDEDNODEID], /* .memberType */
offsetof(UA_ReferenceDescription, nodeId) - offsetof(UA_ReferenceDescription, isForward) - sizeof(UA_Boolean), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("BrowseName") /* .memberName */
- UA_TYPES_QUALIFIEDNAME, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_QUALIFIEDNAME], /* .memberType */
offsetof(UA_ReferenceDescription, browseName) - offsetof(UA_ReferenceDescription, nodeId) - sizeof(UA_ExpandedNodeId), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("DisplayName") /* .memberName */
- UA_TYPES_LOCALIZEDTEXT, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
offsetof(UA_ReferenceDescription, displayName) - offsetof(UA_ReferenceDescription, browseName) - sizeof(UA_QualifiedName), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("NodeClass") /* .memberName */
- UA_TYPES_NODECLASS, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_NODECLASS], /* .memberType */
offsetof(UA_ReferenceDescription, nodeClass) - offsetof(UA_ReferenceDescription, displayName) - sizeof(UA_LocalizedText), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("TypeDefinition") /* .memberName */
- UA_TYPES_EXPANDEDNODEID, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_EXPANDEDNODEID], /* .memberType */
offsetof(UA_ReferenceDescription, typeDefinition) - offsetof(UA_ReferenceDescription, nodeClass) - sizeof(UA_NodeClass), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* BrowseResult */
static UA_DataTypeMember BrowseResult_members[3] = {
{
UA_TYPENAME("StatusCode") /* .memberName */
- UA_TYPES_STATUSCODE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("ContinuationPoint") /* .memberName */
- UA_TYPES_BYTESTRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */
offsetof(UA_BrowseResult, continuationPoint) - offsetof(UA_BrowseResult, statusCode) - sizeof(UA_StatusCode), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("References") /* .memberName */
- UA_TYPES_REFERENCEDESCRIPTION, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_REFERENCEDESCRIPTION], /* .memberType */
offsetof(UA_BrowseResult, referencesSize) - offsetof(UA_BrowseResult, continuationPoint) - sizeof(UA_ByteString), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* BrowseRequest */
static UA_DataTypeMember BrowseRequest_members[4] = {
{
UA_TYPENAME("RequestHeader") /* .memberName */
- UA_TYPES_REQUESTHEADER, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("View") /* .memberName */
- UA_TYPES_VIEWDESCRIPTION, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_VIEWDESCRIPTION], /* .memberType */
offsetof(UA_BrowseRequest, view) - offsetof(UA_BrowseRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("RequestedMaxReferencesPerNode") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_BrowseRequest, requestedMaxReferencesPerNode) - offsetof(UA_BrowseRequest, view) - sizeof(UA_ViewDescription), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("NodesToBrowse") /* .memberName */
- UA_TYPES_BROWSEDESCRIPTION, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_BROWSEDESCRIPTION], /* .memberType */
offsetof(UA_BrowseRequest, nodesToBrowseSize) - offsetof(UA_BrowseRequest, requestedMaxReferencesPerNode) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* BrowseResponse */
static UA_DataTypeMember BrowseResponse_members[3] = {
{
UA_TYPENAME("ResponseHeader") /* .memberName */
- UA_TYPES_RESPONSEHEADER, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("Results") /* .memberName */
- UA_TYPES_BROWSERESULT, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_BROWSERESULT], /* .memberType */
offsetof(UA_BrowseResponse, resultsSize) - offsetof(UA_BrowseResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("DiagnosticInfos") /* .memberName */
- UA_TYPES_DIAGNOSTICINFO, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
offsetof(UA_BrowseResponse, diagnosticInfosSize) - offsetof(UA_BrowseResponse, results) - sizeof(void *), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* BrowseNextRequest */
static UA_DataTypeMember BrowseNextRequest_members[3] = {
{
UA_TYPENAME("RequestHeader") /* .memberName */
- UA_TYPES_REQUESTHEADER, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("ReleaseContinuationPoints") /* .memberName */
- UA_TYPES_BOOLEAN, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
offsetof(UA_BrowseNextRequest, releaseContinuationPoints) - offsetof(UA_BrowseNextRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("ContinuationPoints") /* .memberName */
- UA_TYPES_BYTESTRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */
offsetof(UA_BrowseNextRequest, continuationPointsSize) - offsetof(UA_BrowseNextRequest, releaseContinuationPoints) - sizeof(UA_Boolean), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* BrowseNextResponse */
static UA_DataTypeMember BrowseNextResponse_members[3] = {
{
UA_TYPENAME("ResponseHeader") /* .memberName */
- UA_TYPES_RESPONSEHEADER, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("Results") /* .memberName */
- UA_TYPES_BROWSERESULT, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_BROWSERESULT], /* .memberType */
offsetof(UA_BrowseNextResponse, resultsSize) - offsetof(UA_BrowseNextResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("DiagnosticInfos") /* .memberName */
- UA_TYPES_DIAGNOSTICINFO, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
offsetof(UA_BrowseNextResponse, diagnosticInfosSize) - offsetof(UA_BrowseNextResponse, results) - sizeof(void *), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* RelativePathElement */
static UA_DataTypeMember RelativePathElement_members[4] = {
{
UA_TYPENAME("ReferenceTypeId") /* .memberName */
- UA_TYPES_NODEID, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("IsInverse") /* .memberName */
- UA_TYPES_BOOLEAN, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
offsetof(UA_RelativePathElement, isInverse) - offsetof(UA_RelativePathElement, referenceTypeId) - sizeof(UA_NodeId), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("IncludeSubtypes") /* .memberName */
- UA_TYPES_BOOLEAN, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
offsetof(UA_RelativePathElement, includeSubtypes) - offsetof(UA_RelativePathElement, isInverse) - sizeof(UA_Boolean), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("TargetName") /* .memberName */
- UA_TYPES_QUALIFIEDNAME, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_QUALIFIEDNAME], /* .memberType */
offsetof(UA_RelativePathElement, targetName) - offsetof(UA_RelativePathElement, includeSubtypes) - sizeof(UA_Boolean), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* RelativePath */
static UA_DataTypeMember RelativePath_members[1] = {
{
UA_TYPENAME("Elements") /* .memberName */
- UA_TYPES_RELATIVEPATHELEMENT, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_RELATIVEPATHELEMENT], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* BrowsePath */
static UA_DataTypeMember BrowsePath_members[2] = {
{
UA_TYPENAME("StartingNode") /* .memberName */
- UA_TYPES_NODEID, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("RelativePath") /* .memberName */
- UA_TYPES_RELATIVEPATH, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_RELATIVEPATH], /* .memberType */
offsetof(UA_BrowsePath, relativePath) - offsetof(UA_BrowsePath, startingNode) - sizeof(UA_NodeId), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* BrowsePathTarget */
static UA_DataTypeMember BrowsePathTarget_members[2] = {
{
UA_TYPENAME("TargetId") /* .memberName */
- UA_TYPES_EXPANDEDNODEID, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_EXPANDEDNODEID], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("RemainingPathIndex") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_BrowsePathTarget, remainingPathIndex) - offsetof(UA_BrowsePathTarget, targetId) - sizeof(UA_ExpandedNodeId), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* BrowsePathResult */
static UA_DataTypeMember BrowsePathResult_members[2] = {
{
UA_TYPENAME("StatusCode") /* .memberName */
- UA_TYPES_STATUSCODE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("Targets") /* .memberName */
- UA_TYPES_BROWSEPATHTARGET, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_BROWSEPATHTARGET], /* .memberType */
offsetof(UA_BrowsePathResult, targetsSize) - offsetof(UA_BrowsePathResult, statusCode) - sizeof(UA_StatusCode), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* TranslateBrowsePathsToNodeIdsRequest */
static UA_DataTypeMember TranslateBrowsePathsToNodeIdsRequest_members[2] = {
{
UA_TYPENAME("RequestHeader") /* .memberName */
- UA_TYPES_REQUESTHEADER, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("BrowsePaths") /* .memberName */
- UA_TYPES_BROWSEPATH, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_BROWSEPATH], /* .memberType */
offsetof(UA_TranslateBrowsePathsToNodeIdsRequest, browsePathsSize) - offsetof(UA_TranslateBrowsePathsToNodeIdsRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* TranslateBrowsePathsToNodeIdsResponse */
static UA_DataTypeMember TranslateBrowsePathsToNodeIdsResponse_members[3] = {
{
UA_TYPENAME("ResponseHeader") /* .memberName */
- UA_TYPES_RESPONSEHEADER, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("Results") /* .memberName */
- UA_TYPES_BROWSEPATHRESULT, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_BROWSEPATHRESULT], /* .memberType */
offsetof(UA_TranslateBrowsePathsToNodeIdsResponse, resultsSize) - offsetof(UA_TranslateBrowsePathsToNodeIdsResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("DiagnosticInfos") /* .memberName */
- UA_TYPES_DIAGNOSTICINFO, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
offsetof(UA_TranslateBrowsePathsToNodeIdsResponse, diagnosticInfosSize) - offsetof(UA_TranslateBrowsePathsToNodeIdsResponse, results) - sizeof(void *), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* RegisterNodesRequest */
static UA_DataTypeMember RegisterNodesRequest_members[2] = {
{
UA_TYPENAME("RequestHeader") /* .memberName */
- UA_TYPES_REQUESTHEADER, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("NodesToRegister") /* .memberName */
- UA_TYPES_NODEID, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
offsetof(UA_RegisterNodesRequest, nodesToRegisterSize) - offsetof(UA_RegisterNodesRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* RegisterNodesResponse */
static UA_DataTypeMember RegisterNodesResponse_members[2] = {
{
UA_TYPENAME("ResponseHeader") /* .memberName */
- UA_TYPES_RESPONSEHEADER, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("RegisteredNodeIds") /* .memberName */
- UA_TYPES_NODEID, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
offsetof(UA_RegisterNodesResponse, registeredNodeIdsSize) - offsetof(UA_RegisterNodesResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* UnregisterNodesRequest */
static UA_DataTypeMember UnregisterNodesRequest_members[2] = {
{
UA_TYPENAME("RequestHeader") /* .memberName */
- UA_TYPES_REQUESTHEADER, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("NodesToUnregister") /* .memberName */
- UA_TYPES_NODEID, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
offsetof(UA_UnregisterNodesRequest, nodesToUnregisterSize) - offsetof(UA_UnregisterNodesRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* UnregisterNodesResponse */
static UA_DataTypeMember UnregisterNodesResponse_members[1] = {
{
UA_TYPENAME("ResponseHeader") /* .memberName */
- UA_TYPES_RESPONSEHEADER, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* FilterOperator */
@@ -13680,179 +12505,157 @@ static UA_DataTypeMember UnregisterNodesResponse_members[1] = {
static UA_DataTypeMember ContentFilterElement_members[2] = {
{
UA_TYPENAME("FilterOperator") /* .memberName */
- UA_TYPES_FILTEROPERATOR, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_FILTEROPERATOR], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("FilterOperands") /* .memberName */
- UA_TYPES_EXTENSIONOBJECT, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], /* .memberType */
offsetof(UA_ContentFilterElement, filterOperandsSize) - offsetof(UA_ContentFilterElement, filterOperator) - sizeof(UA_FilterOperator), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* ContentFilter */
static UA_DataTypeMember ContentFilter_members[1] = {
{
UA_TYPENAME("Elements") /* .memberName */
- UA_TYPES_CONTENTFILTERELEMENT, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_CONTENTFILTERELEMENT], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
-/* FilterOperand */
-#define FilterOperand_members NULL
-
/* ElementOperand */
static UA_DataTypeMember ElementOperand_members[1] = {
{
UA_TYPENAME("Index") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* LiteralOperand */
static UA_DataTypeMember LiteralOperand_members[1] = {
{
UA_TYPENAME("Value") /* .memberName */
- UA_TYPES_VARIANT, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_VARIANT], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* AttributeOperand */
static UA_DataTypeMember AttributeOperand_members[5] = {
{
UA_TYPENAME("NodeId") /* .memberName */
- UA_TYPES_NODEID, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("Alias") /* .memberName */
- UA_TYPES_STRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STRING], /* .memberType */
offsetof(UA_AttributeOperand, alias) - offsetof(UA_AttributeOperand, nodeId) - sizeof(UA_NodeId), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("BrowsePath") /* .memberName */
- UA_TYPES_RELATIVEPATH, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_RELATIVEPATH], /* .memberType */
offsetof(UA_AttributeOperand, browsePath) - offsetof(UA_AttributeOperand, alias) - sizeof(UA_String), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("AttributeId") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_AttributeOperand, attributeId) - offsetof(UA_AttributeOperand, browsePath) - sizeof(UA_RelativePath), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("IndexRange") /* .memberName */
- UA_TYPES_STRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STRING], /* .memberType */
offsetof(UA_AttributeOperand, indexRange) - offsetof(UA_AttributeOperand, attributeId) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* SimpleAttributeOperand */
static UA_DataTypeMember SimpleAttributeOperand_members[4] = {
{
UA_TYPENAME("TypeDefinitionId") /* .memberName */
- UA_TYPES_NODEID, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("BrowsePath") /* .memberName */
- UA_TYPES_QUALIFIEDNAME, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_QUALIFIEDNAME], /* .memberType */
offsetof(UA_SimpleAttributeOperand, browsePathSize) - offsetof(UA_SimpleAttributeOperand, typeDefinitionId) - sizeof(UA_NodeId), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("AttributeId") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_SimpleAttributeOperand, attributeId) - offsetof(UA_SimpleAttributeOperand, browsePath) - sizeof(void *), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("IndexRange") /* .memberName */
- UA_TYPES_STRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STRING], /* .memberType */
offsetof(UA_SimpleAttributeOperand, indexRange) - offsetof(UA_SimpleAttributeOperand, attributeId) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* ContentFilterElementResult */
static UA_DataTypeMember ContentFilterElementResult_members[3] = {
{
UA_TYPENAME("StatusCode") /* .memberName */
- UA_TYPES_STATUSCODE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("OperandStatusCodes") /* .memberName */
- UA_TYPES_STATUSCODE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
offsetof(UA_ContentFilterElementResult, operandStatusCodesSize) - offsetof(UA_ContentFilterElementResult, statusCode) - sizeof(UA_StatusCode), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("OperandDiagnosticInfos") /* .memberName */
- UA_TYPES_DIAGNOSTICINFO, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
offsetof(UA_ContentFilterElementResult, operandDiagnosticInfosSize) - offsetof(UA_ContentFilterElementResult, operandStatusCodes) - sizeof(void *), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* ContentFilterResult */
static UA_DataTypeMember ContentFilterResult_members[2] = {
{
UA_TYPENAME("ElementResults") /* .memberName */
- UA_TYPES_CONTENTFILTERELEMENTRESULT, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_CONTENTFILTERELEMENTRESULT], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("ElementDiagnosticInfos") /* .memberName */
- UA_TYPES_DIAGNOSTICINFO, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
offsetof(UA_ContentFilterResult, elementDiagnosticInfosSize) - offsetof(UA_ContentFilterResult, elementResults) - sizeof(void *), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* TimestampsToReturn */
@@ -13862,383 +12665,340 @@ static UA_DataTypeMember ContentFilterResult_members[2] = {
static UA_DataTypeMember ReadValueId_members[4] = {
{
UA_TYPENAME("NodeId") /* .memberName */
- UA_TYPES_NODEID, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("AttributeId") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_ReadValueId, attributeId) - offsetof(UA_ReadValueId, nodeId) - sizeof(UA_NodeId), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("IndexRange") /* .memberName */
- UA_TYPES_STRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STRING], /* .memberType */
offsetof(UA_ReadValueId, indexRange) - offsetof(UA_ReadValueId, attributeId) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("DataEncoding") /* .memberName */
- UA_TYPES_QUALIFIEDNAME, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_QUALIFIEDNAME], /* .memberType */
offsetof(UA_ReadValueId, dataEncoding) - offsetof(UA_ReadValueId, indexRange) - sizeof(UA_String), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* ReadRequest */
static UA_DataTypeMember ReadRequest_members[4] = {
{
UA_TYPENAME("RequestHeader") /* .memberName */
- UA_TYPES_REQUESTHEADER, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("MaxAge") /* .memberName */
- UA_TYPES_DOUBLE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */
offsetof(UA_ReadRequest, maxAge) - offsetof(UA_ReadRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("TimestampsToReturn") /* .memberName */
- UA_TYPES_TIMESTAMPSTORETURN, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_TIMESTAMPSTORETURN], /* .memberType */
offsetof(UA_ReadRequest, timestampsToReturn) - offsetof(UA_ReadRequest, maxAge) - sizeof(UA_Double), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("NodesToRead") /* .memberName */
- UA_TYPES_READVALUEID, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_READVALUEID], /* .memberType */
offsetof(UA_ReadRequest, nodesToReadSize) - offsetof(UA_ReadRequest, timestampsToReturn) - sizeof(UA_TimestampsToReturn), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* ReadResponse */
static UA_DataTypeMember ReadResponse_members[3] = {
{
UA_TYPENAME("ResponseHeader") /* .memberName */
- UA_TYPES_RESPONSEHEADER, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("Results") /* .memberName */
- UA_TYPES_DATAVALUE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DATAVALUE], /* .memberType */
offsetof(UA_ReadResponse, resultsSize) - offsetof(UA_ReadResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("DiagnosticInfos") /* .memberName */
- UA_TYPES_DIAGNOSTICINFO, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
offsetof(UA_ReadResponse, diagnosticInfosSize) - offsetof(UA_ReadResponse, results) - sizeof(void *), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* HistoryReadValueId */
static UA_DataTypeMember HistoryReadValueId_members[4] = {
{
UA_TYPENAME("NodeId") /* .memberName */
- UA_TYPES_NODEID, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("IndexRange") /* .memberName */
- UA_TYPES_STRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STRING], /* .memberType */
offsetof(UA_HistoryReadValueId, indexRange) - offsetof(UA_HistoryReadValueId, nodeId) - sizeof(UA_NodeId), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("DataEncoding") /* .memberName */
- UA_TYPES_QUALIFIEDNAME, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_QUALIFIEDNAME], /* .memberType */
offsetof(UA_HistoryReadValueId, dataEncoding) - offsetof(UA_HistoryReadValueId, indexRange) - sizeof(UA_String), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("ContinuationPoint") /* .memberName */
- UA_TYPES_BYTESTRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */
offsetof(UA_HistoryReadValueId, continuationPoint) - offsetof(UA_HistoryReadValueId, dataEncoding) - sizeof(UA_QualifiedName), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* HistoryReadResult */
static UA_DataTypeMember HistoryReadResult_members[3] = {
{
UA_TYPENAME("StatusCode") /* .memberName */
- UA_TYPES_STATUSCODE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("ContinuationPoint") /* .memberName */
- UA_TYPES_BYTESTRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */
offsetof(UA_HistoryReadResult, continuationPoint) - offsetof(UA_HistoryReadResult, statusCode) - sizeof(UA_StatusCode), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("HistoryData") /* .memberName */
- UA_TYPES_EXTENSIONOBJECT, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], /* .memberType */
offsetof(UA_HistoryReadResult, historyData) - offsetof(UA_HistoryReadResult, continuationPoint) - sizeof(UA_ByteString), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* ReadRawModifiedDetails */
static UA_DataTypeMember ReadRawModifiedDetails_members[5] = {
{
UA_TYPENAME("IsReadModified") /* .memberName */
- UA_TYPES_BOOLEAN, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("StartTime") /* .memberName */
- UA_TYPES_DATETIME, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */
offsetof(UA_ReadRawModifiedDetails, startTime) - offsetof(UA_ReadRawModifiedDetails, isReadModified) - sizeof(UA_Boolean), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("EndTime") /* .memberName */
- UA_TYPES_DATETIME, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */
offsetof(UA_ReadRawModifiedDetails, endTime) - offsetof(UA_ReadRawModifiedDetails, startTime) - sizeof(UA_DateTime), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("NumValuesPerNode") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_ReadRawModifiedDetails, numValuesPerNode) - offsetof(UA_ReadRawModifiedDetails, endTime) - sizeof(UA_DateTime), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("ReturnBounds") /* .memberName */
- UA_TYPES_BOOLEAN, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
offsetof(UA_ReadRawModifiedDetails, returnBounds) - offsetof(UA_ReadRawModifiedDetails, numValuesPerNode) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* ReadAtTimeDetails */
static UA_DataTypeMember ReadAtTimeDetails_members[2] = {
{
UA_TYPENAME("ReqTimes") /* .memberName */
- UA_TYPES_DATETIME, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("UseSimpleBounds") /* .memberName */
- UA_TYPES_BOOLEAN, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
offsetof(UA_ReadAtTimeDetails, useSimpleBounds) - offsetof(UA_ReadAtTimeDetails, reqTimes) - sizeof(void *), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* HistoryData */
static UA_DataTypeMember HistoryData_members[1] = {
{
UA_TYPENAME("DataValues") /* .memberName */
- UA_TYPES_DATAVALUE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DATAVALUE], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* HistoryReadRequest */
static UA_DataTypeMember HistoryReadRequest_members[5] = {
{
UA_TYPENAME("RequestHeader") /* .memberName */
- UA_TYPES_REQUESTHEADER, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("HistoryReadDetails") /* .memberName */
- UA_TYPES_EXTENSIONOBJECT, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], /* .memberType */
offsetof(UA_HistoryReadRequest, historyReadDetails) - offsetof(UA_HistoryReadRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("TimestampsToReturn") /* .memberName */
- UA_TYPES_TIMESTAMPSTORETURN, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_TIMESTAMPSTORETURN], /* .memberType */
offsetof(UA_HistoryReadRequest, timestampsToReturn) - offsetof(UA_HistoryReadRequest, historyReadDetails) - sizeof(UA_ExtensionObject), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("ReleaseContinuationPoints") /* .memberName */
- UA_TYPES_BOOLEAN, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
offsetof(UA_HistoryReadRequest, releaseContinuationPoints) - offsetof(UA_HistoryReadRequest, timestampsToReturn) - sizeof(UA_TimestampsToReturn), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("NodesToRead") /* .memberName */
- UA_TYPES_HISTORYREADVALUEID, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_HISTORYREADVALUEID], /* .memberType */
offsetof(UA_HistoryReadRequest, nodesToReadSize) - offsetof(UA_HistoryReadRequest, releaseContinuationPoints) - sizeof(UA_Boolean), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* HistoryReadResponse */
static UA_DataTypeMember HistoryReadResponse_members[3] = {
{
UA_TYPENAME("ResponseHeader") /* .memberName */
- UA_TYPES_RESPONSEHEADER, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("Results") /* .memberName */
- UA_TYPES_HISTORYREADRESULT, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_HISTORYREADRESULT], /* .memberType */
offsetof(UA_HistoryReadResponse, resultsSize) - offsetof(UA_HistoryReadResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("DiagnosticInfos") /* .memberName */
- UA_TYPES_DIAGNOSTICINFO, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
offsetof(UA_HistoryReadResponse, diagnosticInfosSize) - offsetof(UA_HistoryReadResponse, results) - sizeof(void *), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* WriteValue */
static UA_DataTypeMember WriteValue_members[4] = {
{
UA_TYPENAME("NodeId") /* .memberName */
- UA_TYPES_NODEID, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("AttributeId") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_WriteValue, attributeId) - offsetof(UA_WriteValue, nodeId) - sizeof(UA_NodeId), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("IndexRange") /* .memberName */
- UA_TYPES_STRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STRING], /* .memberType */
offsetof(UA_WriteValue, indexRange) - offsetof(UA_WriteValue, attributeId) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("Value") /* .memberName */
- UA_TYPES_DATAVALUE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DATAVALUE], /* .memberType */
offsetof(UA_WriteValue, value) - offsetof(UA_WriteValue, indexRange) - sizeof(UA_String), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* WriteRequest */
static UA_DataTypeMember WriteRequest_members[2] = {
{
UA_TYPENAME("RequestHeader") /* .memberName */
- UA_TYPES_REQUESTHEADER, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("NodesToWrite") /* .memberName */
- UA_TYPES_WRITEVALUE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_WRITEVALUE], /* .memberType */
offsetof(UA_WriteRequest, nodesToWriteSize) - offsetof(UA_WriteRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* WriteResponse */
static UA_DataTypeMember WriteResponse_members[3] = {
{
UA_TYPENAME("ResponseHeader") /* .memberName */
- UA_TYPES_RESPONSEHEADER, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("Results") /* .memberName */
- UA_TYPES_STATUSCODE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
offsetof(UA_WriteResponse, resultsSize) - offsetof(UA_WriteResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("DiagnosticInfos") /* .memberName */
- UA_TYPES_DIAGNOSTICINFO, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
offsetof(UA_WriteResponse, diagnosticInfosSize) - offsetof(UA_WriteResponse, results) - sizeof(void *), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* HistoryUpdateType */
@@ -14251,243 +13011,216 @@ static UA_DataTypeMember WriteResponse_members[3] = {
static UA_DataTypeMember UpdateDataDetails_members[3] = {
{
UA_TYPENAME("NodeId") /* .memberName */
- UA_TYPES_NODEID, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("PerformInsertReplace") /* .memberName */
- UA_TYPES_PERFORMUPDATETYPE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_PERFORMUPDATETYPE], /* .memberType */
offsetof(UA_UpdateDataDetails, performInsertReplace) - offsetof(UA_UpdateDataDetails, nodeId) - sizeof(UA_NodeId), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("UpdateValues") /* .memberName */
- UA_TYPES_DATAVALUE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DATAVALUE], /* .memberType */
offsetof(UA_UpdateDataDetails, updateValuesSize) - offsetof(UA_UpdateDataDetails, performInsertReplace) - sizeof(UA_PerformUpdateType), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* DeleteRawModifiedDetails */
static UA_DataTypeMember DeleteRawModifiedDetails_members[4] = {
{
UA_TYPENAME("NodeId") /* .memberName */
- UA_TYPES_NODEID, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("IsDeleteModified") /* .memberName */
- UA_TYPES_BOOLEAN, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
offsetof(UA_DeleteRawModifiedDetails, isDeleteModified) - offsetof(UA_DeleteRawModifiedDetails, nodeId) - sizeof(UA_NodeId), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("StartTime") /* .memberName */
- UA_TYPES_DATETIME, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */
offsetof(UA_DeleteRawModifiedDetails, startTime) - offsetof(UA_DeleteRawModifiedDetails, isDeleteModified) - sizeof(UA_Boolean), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("EndTime") /* .memberName */
- UA_TYPES_DATETIME, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */
offsetof(UA_DeleteRawModifiedDetails, endTime) - offsetof(UA_DeleteRawModifiedDetails, startTime) - sizeof(UA_DateTime), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* HistoryUpdateResult */
static UA_DataTypeMember HistoryUpdateResult_members[3] = {
{
UA_TYPENAME("StatusCode") /* .memberName */
- UA_TYPES_STATUSCODE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("OperationResults") /* .memberName */
- UA_TYPES_STATUSCODE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
offsetof(UA_HistoryUpdateResult, operationResultsSize) - offsetof(UA_HistoryUpdateResult, statusCode) - sizeof(UA_StatusCode), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("DiagnosticInfos") /* .memberName */
- UA_TYPES_DIAGNOSTICINFO, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
offsetof(UA_HistoryUpdateResult, diagnosticInfosSize) - offsetof(UA_HistoryUpdateResult, operationResults) - sizeof(void *), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* HistoryUpdateRequest */
static UA_DataTypeMember HistoryUpdateRequest_members[2] = {
{
UA_TYPENAME("RequestHeader") /* .memberName */
- UA_TYPES_REQUESTHEADER, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("HistoryUpdateDetails") /* .memberName */
- UA_TYPES_EXTENSIONOBJECT, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], /* .memberType */
offsetof(UA_HistoryUpdateRequest, historyUpdateDetailsSize) - offsetof(UA_HistoryUpdateRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* HistoryUpdateResponse */
static UA_DataTypeMember HistoryUpdateResponse_members[3] = {
{
UA_TYPENAME("ResponseHeader") /* .memberName */
- UA_TYPES_RESPONSEHEADER, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("Results") /* .memberName */
- UA_TYPES_HISTORYUPDATERESULT, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_HISTORYUPDATERESULT], /* .memberType */
offsetof(UA_HistoryUpdateResponse, resultsSize) - offsetof(UA_HistoryUpdateResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("DiagnosticInfos") /* .memberName */
- UA_TYPES_DIAGNOSTICINFO, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
offsetof(UA_HistoryUpdateResponse, diagnosticInfosSize) - offsetof(UA_HistoryUpdateResponse, results) - sizeof(void *), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* CallMethodRequest */
static UA_DataTypeMember CallMethodRequest_members[3] = {
{
UA_TYPENAME("ObjectId") /* .memberName */
- UA_TYPES_NODEID, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("MethodId") /* .memberName */
- UA_TYPES_NODEID, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
offsetof(UA_CallMethodRequest, methodId) - offsetof(UA_CallMethodRequest, objectId) - sizeof(UA_NodeId), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("InputArguments") /* .memberName */
- UA_TYPES_VARIANT, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_VARIANT], /* .memberType */
offsetof(UA_CallMethodRequest, inputArgumentsSize) - offsetof(UA_CallMethodRequest, methodId) - sizeof(UA_NodeId), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* CallMethodResult */
static UA_DataTypeMember CallMethodResult_members[4] = {
{
UA_TYPENAME("StatusCode") /* .memberName */
- UA_TYPES_STATUSCODE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("InputArgumentResults") /* .memberName */
- UA_TYPES_STATUSCODE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
offsetof(UA_CallMethodResult, inputArgumentResultsSize) - offsetof(UA_CallMethodResult, statusCode) - sizeof(UA_StatusCode), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("InputArgumentDiagnosticInfos") /* .memberName */
- UA_TYPES_DIAGNOSTICINFO, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
offsetof(UA_CallMethodResult, inputArgumentDiagnosticInfosSize) - offsetof(UA_CallMethodResult, inputArgumentResults) - sizeof(void *), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("OutputArguments") /* .memberName */
- UA_TYPES_VARIANT, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_VARIANT], /* .memberType */
offsetof(UA_CallMethodResult, outputArgumentsSize) - offsetof(UA_CallMethodResult, inputArgumentDiagnosticInfos) - sizeof(void *), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* CallRequest */
static UA_DataTypeMember CallRequest_members[2] = {
{
UA_TYPENAME("RequestHeader") /* .memberName */
- UA_TYPES_REQUESTHEADER, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("MethodsToCall") /* .memberName */
- UA_TYPES_CALLMETHODREQUEST, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_CALLMETHODREQUEST], /* .memberType */
offsetof(UA_CallRequest, methodsToCallSize) - offsetof(UA_CallRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* CallResponse */
static UA_DataTypeMember CallResponse_members[3] = {
{
UA_TYPENAME("ResponseHeader") /* .memberName */
- UA_TYPES_RESPONSEHEADER, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("Results") /* .memberName */
- UA_TYPES_CALLMETHODRESULT, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_CALLMETHODRESULT], /* .memberType */
offsetof(UA_CallResponse, resultsSize) - offsetof(UA_CallResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("DiagnosticInfos") /* .memberName */
- UA_TYPES_DIAGNOSTICINFO, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
offsetof(UA_CallResponse, diagnosticInfosSize) - offsetof(UA_CallResponse, results) - sizeof(void *), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* MonitoringMode */
@@ -14503,1229 +13236,1155 @@ static UA_DataTypeMember CallResponse_members[3] = {
static UA_DataTypeMember DataChangeFilter_members[3] = {
{
UA_TYPENAME("Trigger") /* .memberName */
- UA_TYPES_DATACHANGETRIGGER, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DATACHANGETRIGGER], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("DeadbandType") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_DataChangeFilter, deadbandType) - offsetof(UA_DataChangeFilter, trigger) - sizeof(UA_DataChangeTrigger), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("DeadbandValue") /* .memberName */
- UA_TYPES_DOUBLE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */
offsetof(UA_DataChangeFilter, deadbandValue) - offsetof(UA_DataChangeFilter, deadbandType) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* EventFilter */
static UA_DataTypeMember EventFilter_members[2] = {
{
UA_TYPENAME("SelectClauses") /* .memberName */
- UA_TYPES_SIMPLEATTRIBUTEOPERAND, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_SIMPLEATTRIBUTEOPERAND], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("WhereClause") /* .memberName */
- UA_TYPES_CONTENTFILTER, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_CONTENTFILTER], /* .memberType */
offsetof(UA_EventFilter, whereClause) - offsetof(UA_EventFilter, selectClauses) - sizeof(void *), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* AggregateConfiguration */
static UA_DataTypeMember AggregateConfiguration_members[5] = {
{
UA_TYPENAME("UseServerCapabilitiesDefaults") /* .memberName */
- UA_TYPES_BOOLEAN, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("TreatUncertainAsBad") /* .memberName */
- UA_TYPES_BOOLEAN, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
offsetof(UA_AggregateConfiguration, treatUncertainAsBad) - offsetof(UA_AggregateConfiguration, useServerCapabilitiesDefaults) - sizeof(UA_Boolean), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("PercentDataBad") /* .memberName */
- UA_TYPES_BYTE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_BYTE], /* .memberType */
offsetof(UA_AggregateConfiguration, percentDataBad) - offsetof(UA_AggregateConfiguration, treatUncertainAsBad) - sizeof(UA_Boolean), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("PercentDataGood") /* .memberName */
- UA_TYPES_BYTE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_BYTE], /* .memberType */
offsetof(UA_AggregateConfiguration, percentDataGood) - offsetof(UA_AggregateConfiguration, percentDataBad) - sizeof(UA_Byte), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("UseSlopedExtrapolation") /* .memberName */
- UA_TYPES_BOOLEAN, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
offsetof(UA_AggregateConfiguration, useSlopedExtrapolation) - offsetof(UA_AggregateConfiguration, percentDataGood) - sizeof(UA_Byte), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* AggregateFilter */
static UA_DataTypeMember AggregateFilter_members[4] = {
{
UA_TYPENAME("StartTime") /* .memberName */
- UA_TYPES_DATETIME, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("AggregateType") /* .memberName */
- UA_TYPES_NODEID, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
offsetof(UA_AggregateFilter, aggregateType) - offsetof(UA_AggregateFilter, startTime) - sizeof(UA_DateTime), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("ProcessingInterval") /* .memberName */
- UA_TYPES_DOUBLE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */
offsetof(UA_AggregateFilter, processingInterval) - offsetof(UA_AggregateFilter, aggregateType) - sizeof(UA_NodeId), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("AggregateConfiguration") /* .memberName */
- UA_TYPES_AGGREGATECONFIGURATION, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_AGGREGATECONFIGURATION], /* .memberType */
offsetof(UA_AggregateFilter, aggregateConfiguration) - offsetof(UA_AggregateFilter, processingInterval) - sizeof(UA_Double), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* EventFilterResult */
static UA_DataTypeMember EventFilterResult_members[3] = {
{
UA_TYPENAME("SelectClauseResults") /* .memberName */
- UA_TYPES_STATUSCODE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("SelectClauseDiagnosticInfos") /* .memberName */
- UA_TYPES_DIAGNOSTICINFO, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
offsetof(UA_EventFilterResult, selectClauseDiagnosticInfosSize) - offsetof(UA_EventFilterResult, selectClauseResults) - sizeof(void *), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("WhereClauseResult") /* .memberName */
- UA_TYPES_CONTENTFILTERRESULT, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_CONTENTFILTERRESULT], /* .memberType */
offsetof(UA_EventFilterResult, whereClauseResult) - offsetof(UA_EventFilterResult, selectClauseDiagnosticInfos) - sizeof(void *), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* MonitoringParameters */
static UA_DataTypeMember MonitoringParameters_members[5] = {
{
UA_TYPENAME("ClientHandle") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("SamplingInterval") /* .memberName */
- UA_TYPES_DOUBLE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */
offsetof(UA_MonitoringParameters, samplingInterval) - offsetof(UA_MonitoringParameters, clientHandle) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("Filter") /* .memberName */
- UA_TYPES_EXTENSIONOBJECT, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], /* .memberType */
offsetof(UA_MonitoringParameters, filter) - offsetof(UA_MonitoringParameters, samplingInterval) - sizeof(UA_Double), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("QueueSize") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_MonitoringParameters, queueSize) - offsetof(UA_MonitoringParameters, filter) - sizeof(UA_ExtensionObject), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("DiscardOldest") /* .memberName */
- UA_TYPES_BOOLEAN, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
offsetof(UA_MonitoringParameters, discardOldest) - offsetof(UA_MonitoringParameters, queueSize) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* MonitoredItemCreateRequest */
static UA_DataTypeMember MonitoredItemCreateRequest_members[3] = {
{
UA_TYPENAME("ItemToMonitor") /* .memberName */
- UA_TYPES_READVALUEID, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_READVALUEID], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("MonitoringMode") /* .memberName */
- UA_TYPES_MONITORINGMODE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_MONITORINGMODE], /* .memberType */
offsetof(UA_MonitoredItemCreateRequest, monitoringMode) - offsetof(UA_MonitoredItemCreateRequest, itemToMonitor) - sizeof(UA_ReadValueId), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("RequestedParameters") /* .memberName */
- UA_TYPES_MONITORINGPARAMETERS, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_MONITORINGPARAMETERS], /* .memberType */
offsetof(UA_MonitoredItemCreateRequest, requestedParameters) - offsetof(UA_MonitoredItemCreateRequest, monitoringMode) - sizeof(UA_MonitoringMode), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* MonitoredItemCreateResult */
static UA_DataTypeMember MonitoredItemCreateResult_members[5] = {
{
UA_TYPENAME("StatusCode") /* .memberName */
- UA_TYPES_STATUSCODE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("MonitoredItemId") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_MonitoredItemCreateResult, monitoredItemId) - offsetof(UA_MonitoredItemCreateResult, statusCode) - sizeof(UA_StatusCode), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("RevisedSamplingInterval") /* .memberName */
- UA_TYPES_DOUBLE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */
offsetof(UA_MonitoredItemCreateResult, revisedSamplingInterval) - offsetof(UA_MonitoredItemCreateResult, monitoredItemId) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("RevisedQueueSize") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_MonitoredItemCreateResult, revisedQueueSize) - offsetof(UA_MonitoredItemCreateResult, revisedSamplingInterval) - sizeof(UA_Double), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("FilterResult") /* .memberName */
- UA_TYPES_EXTENSIONOBJECT, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], /* .memberType */
offsetof(UA_MonitoredItemCreateResult, filterResult) - offsetof(UA_MonitoredItemCreateResult, revisedQueueSize) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* CreateMonitoredItemsRequest */
static UA_DataTypeMember CreateMonitoredItemsRequest_members[4] = {
{
UA_TYPENAME("RequestHeader") /* .memberName */
- UA_TYPES_REQUESTHEADER, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("SubscriptionId") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_CreateMonitoredItemsRequest, subscriptionId) - offsetof(UA_CreateMonitoredItemsRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("TimestampsToReturn") /* .memberName */
- UA_TYPES_TIMESTAMPSTORETURN, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_TIMESTAMPSTORETURN], /* .memberType */
offsetof(UA_CreateMonitoredItemsRequest, timestampsToReturn) - offsetof(UA_CreateMonitoredItemsRequest, subscriptionId) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("ItemsToCreate") /* .memberName */
- UA_TYPES_MONITOREDITEMCREATEREQUEST, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_MONITOREDITEMCREATEREQUEST], /* .memberType */
offsetof(UA_CreateMonitoredItemsRequest, itemsToCreateSize) - offsetof(UA_CreateMonitoredItemsRequest, timestampsToReturn) - sizeof(UA_TimestampsToReturn), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* CreateMonitoredItemsResponse */
static UA_DataTypeMember CreateMonitoredItemsResponse_members[3] = {
{
UA_TYPENAME("ResponseHeader") /* .memberName */
- UA_TYPES_RESPONSEHEADER, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("Results") /* .memberName */
- UA_TYPES_MONITOREDITEMCREATERESULT, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_MONITOREDITEMCREATERESULT], /* .memberType */
offsetof(UA_CreateMonitoredItemsResponse, resultsSize) - offsetof(UA_CreateMonitoredItemsResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("DiagnosticInfos") /* .memberName */
- UA_TYPES_DIAGNOSTICINFO, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
offsetof(UA_CreateMonitoredItemsResponse, diagnosticInfosSize) - offsetof(UA_CreateMonitoredItemsResponse, results) - sizeof(void *), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* MonitoredItemModifyRequest */
static UA_DataTypeMember MonitoredItemModifyRequest_members[2] = {
{
UA_TYPENAME("MonitoredItemId") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("RequestedParameters") /* .memberName */
- UA_TYPES_MONITORINGPARAMETERS, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_MONITORINGPARAMETERS], /* .memberType */
offsetof(UA_MonitoredItemModifyRequest, requestedParameters) - offsetof(UA_MonitoredItemModifyRequest, monitoredItemId) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* MonitoredItemModifyResult */
static UA_DataTypeMember MonitoredItemModifyResult_members[4] = {
{
UA_TYPENAME("StatusCode") /* .memberName */
- UA_TYPES_STATUSCODE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("RevisedSamplingInterval") /* .memberName */
- UA_TYPES_DOUBLE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */
offsetof(UA_MonitoredItemModifyResult, revisedSamplingInterval) - offsetof(UA_MonitoredItemModifyResult, statusCode) - sizeof(UA_StatusCode), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("RevisedQueueSize") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_MonitoredItemModifyResult, revisedQueueSize) - offsetof(UA_MonitoredItemModifyResult, revisedSamplingInterval) - sizeof(UA_Double), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("FilterResult") /* .memberName */
- UA_TYPES_EXTENSIONOBJECT, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], /* .memberType */
offsetof(UA_MonitoredItemModifyResult, filterResult) - offsetof(UA_MonitoredItemModifyResult, revisedQueueSize) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* ModifyMonitoredItemsRequest */
static UA_DataTypeMember ModifyMonitoredItemsRequest_members[4] = {
{
UA_TYPENAME("RequestHeader") /* .memberName */
- UA_TYPES_REQUESTHEADER, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("SubscriptionId") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_ModifyMonitoredItemsRequest, subscriptionId) - offsetof(UA_ModifyMonitoredItemsRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("TimestampsToReturn") /* .memberName */
- UA_TYPES_TIMESTAMPSTORETURN, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_TIMESTAMPSTORETURN], /* .memberType */
offsetof(UA_ModifyMonitoredItemsRequest, timestampsToReturn) - offsetof(UA_ModifyMonitoredItemsRequest, subscriptionId) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("ItemsToModify") /* .memberName */
- UA_TYPES_MONITOREDITEMMODIFYREQUEST, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_MONITOREDITEMMODIFYREQUEST], /* .memberType */
offsetof(UA_ModifyMonitoredItemsRequest, itemsToModifySize) - offsetof(UA_ModifyMonitoredItemsRequest, timestampsToReturn) - sizeof(UA_TimestampsToReturn), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* ModifyMonitoredItemsResponse */
static UA_DataTypeMember ModifyMonitoredItemsResponse_members[3] = {
{
UA_TYPENAME("ResponseHeader") /* .memberName */
- UA_TYPES_RESPONSEHEADER, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("Results") /* .memberName */
- UA_TYPES_MONITOREDITEMMODIFYRESULT, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_MONITOREDITEMMODIFYRESULT], /* .memberType */
offsetof(UA_ModifyMonitoredItemsResponse, resultsSize) - offsetof(UA_ModifyMonitoredItemsResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("DiagnosticInfos") /* .memberName */
- UA_TYPES_DIAGNOSTICINFO, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
offsetof(UA_ModifyMonitoredItemsResponse, diagnosticInfosSize) - offsetof(UA_ModifyMonitoredItemsResponse, results) - sizeof(void *), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* SetMonitoringModeRequest */
static UA_DataTypeMember SetMonitoringModeRequest_members[4] = {
{
UA_TYPENAME("RequestHeader") /* .memberName */
- UA_TYPES_REQUESTHEADER, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("SubscriptionId") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_SetMonitoringModeRequest, subscriptionId) - offsetof(UA_SetMonitoringModeRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("MonitoringMode") /* .memberName */
- UA_TYPES_MONITORINGMODE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_MONITORINGMODE], /* .memberType */
offsetof(UA_SetMonitoringModeRequest, monitoringMode) - offsetof(UA_SetMonitoringModeRequest, subscriptionId) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("MonitoredItemIds") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_SetMonitoringModeRequest, monitoredItemIdsSize) - offsetof(UA_SetMonitoringModeRequest, monitoringMode) - sizeof(UA_MonitoringMode), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* SetMonitoringModeResponse */
static UA_DataTypeMember SetMonitoringModeResponse_members[3] = {
{
UA_TYPENAME("ResponseHeader") /* .memberName */
- UA_TYPES_RESPONSEHEADER, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("Results") /* .memberName */
- UA_TYPES_STATUSCODE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
offsetof(UA_SetMonitoringModeResponse, resultsSize) - offsetof(UA_SetMonitoringModeResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("DiagnosticInfos") /* .memberName */
- UA_TYPES_DIAGNOSTICINFO, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
offsetof(UA_SetMonitoringModeResponse, diagnosticInfosSize) - offsetof(UA_SetMonitoringModeResponse, results) - sizeof(void *), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* SetTriggeringRequest */
static UA_DataTypeMember SetTriggeringRequest_members[5] = {
{
UA_TYPENAME("RequestHeader") /* .memberName */
- UA_TYPES_REQUESTHEADER, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("SubscriptionId") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_SetTriggeringRequest, subscriptionId) - offsetof(UA_SetTriggeringRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("TriggeringItemId") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_SetTriggeringRequest, triggeringItemId) - offsetof(UA_SetTriggeringRequest, subscriptionId) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("LinksToAdd") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_SetTriggeringRequest, linksToAddSize) - offsetof(UA_SetTriggeringRequest, triggeringItemId) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("LinksToRemove") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_SetTriggeringRequest, linksToRemoveSize) - offsetof(UA_SetTriggeringRequest, linksToAdd) - sizeof(void *), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* SetTriggeringResponse */
static UA_DataTypeMember SetTriggeringResponse_members[5] = {
{
UA_TYPENAME("ResponseHeader") /* .memberName */
- UA_TYPES_RESPONSEHEADER, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("AddResults") /* .memberName */
- UA_TYPES_STATUSCODE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
offsetof(UA_SetTriggeringResponse, addResultsSize) - offsetof(UA_SetTriggeringResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("AddDiagnosticInfos") /* .memberName */
- UA_TYPES_DIAGNOSTICINFO, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
offsetof(UA_SetTriggeringResponse, addDiagnosticInfosSize) - offsetof(UA_SetTriggeringResponse, addResults) - sizeof(void *), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("RemoveResults") /* .memberName */
- UA_TYPES_STATUSCODE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
offsetof(UA_SetTriggeringResponse, removeResultsSize) - offsetof(UA_SetTriggeringResponse, addDiagnosticInfos) - sizeof(void *), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("RemoveDiagnosticInfos") /* .memberName */
- UA_TYPES_DIAGNOSTICINFO, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
offsetof(UA_SetTriggeringResponse, removeDiagnosticInfosSize) - offsetof(UA_SetTriggeringResponse, removeResults) - sizeof(void *), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* DeleteMonitoredItemsRequest */
static UA_DataTypeMember DeleteMonitoredItemsRequest_members[3] = {
{
UA_TYPENAME("RequestHeader") /* .memberName */
- UA_TYPES_REQUESTHEADER, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("SubscriptionId") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_DeleteMonitoredItemsRequest, subscriptionId) - offsetof(UA_DeleteMonitoredItemsRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("MonitoredItemIds") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_DeleteMonitoredItemsRequest, monitoredItemIdsSize) - offsetof(UA_DeleteMonitoredItemsRequest, subscriptionId) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* DeleteMonitoredItemsResponse */
static UA_DataTypeMember DeleteMonitoredItemsResponse_members[3] = {
{
UA_TYPENAME("ResponseHeader") /* .memberName */
- UA_TYPES_RESPONSEHEADER, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("Results") /* .memberName */
- UA_TYPES_STATUSCODE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
offsetof(UA_DeleteMonitoredItemsResponse, resultsSize) - offsetof(UA_DeleteMonitoredItemsResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("DiagnosticInfos") /* .memberName */
- UA_TYPES_DIAGNOSTICINFO, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
offsetof(UA_DeleteMonitoredItemsResponse, diagnosticInfosSize) - offsetof(UA_DeleteMonitoredItemsResponse, results) - sizeof(void *), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* CreateSubscriptionRequest */
static UA_DataTypeMember CreateSubscriptionRequest_members[7] = {
{
UA_TYPENAME("RequestHeader") /* .memberName */
- UA_TYPES_REQUESTHEADER, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("RequestedPublishingInterval") /* .memberName */
- UA_TYPES_DOUBLE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */
offsetof(UA_CreateSubscriptionRequest, requestedPublishingInterval) - offsetof(UA_CreateSubscriptionRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("RequestedLifetimeCount") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_CreateSubscriptionRequest, requestedLifetimeCount) - offsetof(UA_CreateSubscriptionRequest, requestedPublishingInterval) - sizeof(UA_Double), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("RequestedMaxKeepAliveCount") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_CreateSubscriptionRequest, requestedMaxKeepAliveCount) - offsetof(UA_CreateSubscriptionRequest, requestedLifetimeCount) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("MaxNotificationsPerPublish") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_CreateSubscriptionRequest, maxNotificationsPerPublish) - offsetof(UA_CreateSubscriptionRequest, requestedMaxKeepAliveCount) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("PublishingEnabled") /* .memberName */
- UA_TYPES_BOOLEAN, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
offsetof(UA_CreateSubscriptionRequest, publishingEnabled) - offsetof(UA_CreateSubscriptionRequest, maxNotificationsPerPublish) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("Priority") /* .memberName */
- UA_TYPES_BYTE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_BYTE], /* .memberType */
offsetof(UA_CreateSubscriptionRequest, priority) - offsetof(UA_CreateSubscriptionRequest, publishingEnabled) - sizeof(UA_Boolean), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* CreateSubscriptionResponse */
static UA_DataTypeMember CreateSubscriptionResponse_members[5] = {
{
UA_TYPENAME("ResponseHeader") /* .memberName */
- UA_TYPES_RESPONSEHEADER, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("SubscriptionId") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_CreateSubscriptionResponse, subscriptionId) - offsetof(UA_CreateSubscriptionResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("RevisedPublishingInterval") /* .memberName */
- UA_TYPES_DOUBLE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */
offsetof(UA_CreateSubscriptionResponse, revisedPublishingInterval) - offsetof(UA_CreateSubscriptionResponse, subscriptionId) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("RevisedLifetimeCount") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_CreateSubscriptionResponse, revisedLifetimeCount) - offsetof(UA_CreateSubscriptionResponse, revisedPublishingInterval) - sizeof(UA_Double), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("RevisedMaxKeepAliveCount") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_CreateSubscriptionResponse, revisedMaxKeepAliveCount) - offsetof(UA_CreateSubscriptionResponse, revisedLifetimeCount) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* ModifySubscriptionRequest */
static UA_DataTypeMember ModifySubscriptionRequest_members[7] = {
{
UA_TYPENAME("RequestHeader") /* .memberName */
- UA_TYPES_REQUESTHEADER, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("SubscriptionId") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_ModifySubscriptionRequest, subscriptionId) - offsetof(UA_ModifySubscriptionRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("RequestedPublishingInterval") /* .memberName */
- UA_TYPES_DOUBLE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */
offsetof(UA_ModifySubscriptionRequest, requestedPublishingInterval) - offsetof(UA_ModifySubscriptionRequest, subscriptionId) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("RequestedLifetimeCount") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_ModifySubscriptionRequest, requestedLifetimeCount) - offsetof(UA_ModifySubscriptionRequest, requestedPublishingInterval) - sizeof(UA_Double), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("RequestedMaxKeepAliveCount") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_ModifySubscriptionRequest, requestedMaxKeepAliveCount) - offsetof(UA_ModifySubscriptionRequest, requestedLifetimeCount) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("MaxNotificationsPerPublish") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_ModifySubscriptionRequest, maxNotificationsPerPublish) - offsetof(UA_ModifySubscriptionRequest, requestedMaxKeepAliveCount) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("Priority") /* .memberName */
- UA_TYPES_BYTE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_BYTE], /* .memberType */
offsetof(UA_ModifySubscriptionRequest, priority) - offsetof(UA_ModifySubscriptionRequest, maxNotificationsPerPublish) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* ModifySubscriptionResponse */
static UA_DataTypeMember ModifySubscriptionResponse_members[4] = {
{
UA_TYPENAME("ResponseHeader") /* .memberName */
- UA_TYPES_RESPONSEHEADER, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("RevisedPublishingInterval") /* .memberName */
- UA_TYPES_DOUBLE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */
offsetof(UA_ModifySubscriptionResponse, revisedPublishingInterval) - offsetof(UA_ModifySubscriptionResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("RevisedLifetimeCount") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_ModifySubscriptionResponse, revisedLifetimeCount) - offsetof(UA_ModifySubscriptionResponse, revisedPublishingInterval) - sizeof(UA_Double), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("RevisedMaxKeepAliveCount") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_ModifySubscriptionResponse, revisedMaxKeepAliveCount) - offsetof(UA_ModifySubscriptionResponse, revisedLifetimeCount) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* SetPublishingModeRequest */
static UA_DataTypeMember SetPublishingModeRequest_members[3] = {
{
UA_TYPENAME("RequestHeader") /* .memberName */
- UA_TYPES_REQUESTHEADER, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("PublishingEnabled") /* .memberName */
- UA_TYPES_BOOLEAN, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
offsetof(UA_SetPublishingModeRequest, publishingEnabled) - offsetof(UA_SetPublishingModeRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("SubscriptionIds") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_SetPublishingModeRequest, subscriptionIdsSize) - offsetof(UA_SetPublishingModeRequest, publishingEnabled) - sizeof(UA_Boolean), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* SetPublishingModeResponse */
static UA_DataTypeMember SetPublishingModeResponse_members[3] = {
{
UA_TYPENAME("ResponseHeader") /* .memberName */
- UA_TYPES_RESPONSEHEADER, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("Results") /* .memberName */
- UA_TYPES_STATUSCODE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
offsetof(UA_SetPublishingModeResponse, resultsSize) - offsetof(UA_SetPublishingModeResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("DiagnosticInfos") /* .memberName */
- UA_TYPES_DIAGNOSTICINFO, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
offsetof(UA_SetPublishingModeResponse, diagnosticInfosSize) - offsetof(UA_SetPublishingModeResponse, results) - sizeof(void *), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* NotificationMessage */
static UA_DataTypeMember NotificationMessage_members[3] = {
{
UA_TYPENAME("SequenceNumber") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("PublishTime") /* .memberName */
- UA_TYPES_DATETIME, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */
offsetof(UA_NotificationMessage, publishTime) - offsetof(UA_NotificationMessage, sequenceNumber) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("NotificationData") /* .memberName */
- UA_TYPES_EXTENSIONOBJECT, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], /* .memberType */
offsetof(UA_NotificationMessage, notificationDataSize) - offsetof(UA_NotificationMessage, publishTime) - sizeof(UA_DateTime), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* MonitoredItemNotification */
static UA_DataTypeMember MonitoredItemNotification_members[2] = {
{
UA_TYPENAME("ClientHandle") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("Value") /* .memberName */
- UA_TYPES_DATAVALUE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DATAVALUE], /* .memberType */
offsetof(UA_MonitoredItemNotification, value) - offsetof(UA_MonitoredItemNotification, clientHandle) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* EventFieldList */
static UA_DataTypeMember EventFieldList_members[2] = {
{
UA_TYPENAME("ClientHandle") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("EventFields") /* .memberName */
- UA_TYPES_VARIANT, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_VARIANT], /* .memberType */
offsetof(UA_EventFieldList, eventFieldsSize) - offsetof(UA_EventFieldList, clientHandle) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* HistoryEventFieldList */
static UA_DataTypeMember HistoryEventFieldList_members[1] = {
{
UA_TYPENAME("EventFields") /* .memberName */
- UA_TYPES_VARIANT, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_VARIANT], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* StatusChangeNotification */
static UA_DataTypeMember StatusChangeNotification_members[2] = {
{
UA_TYPENAME("Status") /* .memberName */
- UA_TYPES_STATUSCODE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("DiagnosticInfo") /* .memberName */
- UA_TYPES_DIAGNOSTICINFO, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
offsetof(UA_StatusChangeNotification, diagnosticInfo) - offsetof(UA_StatusChangeNotification, status) - sizeof(UA_StatusCode), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* SubscriptionAcknowledgement */
static UA_DataTypeMember SubscriptionAcknowledgement_members[2] = {
{
UA_TYPENAME("SubscriptionId") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("SequenceNumber") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_SubscriptionAcknowledgement, sequenceNumber) - offsetof(UA_SubscriptionAcknowledgement, subscriptionId) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* PublishRequest */
static UA_DataTypeMember PublishRequest_members[2] = {
{
UA_TYPENAME("RequestHeader") /* .memberName */
- UA_TYPES_REQUESTHEADER, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("SubscriptionAcknowledgements") /* .memberName */
- UA_TYPES_SUBSCRIPTIONACKNOWLEDGEMENT, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_SUBSCRIPTIONACKNOWLEDGEMENT], /* .memberType */
offsetof(UA_PublishRequest, subscriptionAcknowledgementsSize) - offsetof(UA_PublishRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* PublishResponse */
static UA_DataTypeMember PublishResponse_members[7] = {
{
UA_TYPENAME("ResponseHeader") /* .memberName */
- UA_TYPES_RESPONSEHEADER, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("SubscriptionId") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_PublishResponse, subscriptionId) - offsetof(UA_PublishResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("AvailableSequenceNumbers") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_PublishResponse, availableSequenceNumbersSize) - offsetof(UA_PublishResponse, subscriptionId) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("MoreNotifications") /* .memberName */
- UA_TYPES_BOOLEAN, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
offsetof(UA_PublishResponse, moreNotifications) - offsetof(UA_PublishResponse, availableSequenceNumbers) - sizeof(void *), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("NotificationMessage") /* .memberName */
- UA_TYPES_NOTIFICATIONMESSAGE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_NOTIFICATIONMESSAGE], /* .memberType */
offsetof(UA_PublishResponse, notificationMessage) - offsetof(UA_PublishResponse, moreNotifications) - sizeof(UA_Boolean), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("Results") /* .memberName */
- UA_TYPES_STATUSCODE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
offsetof(UA_PublishResponse, resultsSize) - offsetof(UA_PublishResponse, notificationMessage) - sizeof(UA_NotificationMessage), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("DiagnosticInfos") /* .memberName */
- UA_TYPES_DIAGNOSTICINFO, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
offsetof(UA_PublishResponse, diagnosticInfosSize) - offsetof(UA_PublishResponse, results) - sizeof(void *), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* RepublishRequest */
static UA_DataTypeMember RepublishRequest_members[3] = {
{
UA_TYPENAME("RequestHeader") /* .memberName */
- UA_TYPES_REQUESTHEADER, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("SubscriptionId") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_RepublishRequest, subscriptionId) - offsetof(UA_RepublishRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("RetransmitSequenceNumber") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_RepublishRequest, retransmitSequenceNumber) - offsetof(UA_RepublishRequest, subscriptionId) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* RepublishResponse */
static UA_DataTypeMember RepublishResponse_members[2] = {
{
UA_TYPENAME("ResponseHeader") /* .memberName */
- UA_TYPES_RESPONSEHEADER, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("NotificationMessage") /* .memberName */
- UA_TYPES_NOTIFICATIONMESSAGE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_NOTIFICATIONMESSAGE], /* .memberType */
offsetof(UA_RepublishResponse, notificationMessage) - offsetof(UA_RepublishResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
+},};
+
+/* TransferResult */
+static UA_DataTypeMember TransferResult_members[2] = {
+{
+ UA_TYPENAME("StatusCode") /* .memberName */
+ &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
+ 0, /* .padding */
+ false, /* .isArray */
+ false /* .isOptional */
+},
+{
+ UA_TYPENAME("AvailableSequenceNumbers") /* .memberName */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
+ offsetof(UA_TransferResult, availableSequenceNumbersSize) - offsetof(UA_TransferResult, statusCode) - sizeof(UA_StatusCode), /* .padding */
+ true, /* .isArray */
+ false /* .isOptional */
+},};
+
+/* TransferSubscriptionsRequest */
+static UA_DataTypeMember TransferSubscriptionsRequest_members[3] = {
+{
+ UA_TYPENAME("RequestHeader") /* .memberName */
+ &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
+ 0, /* .padding */
+ false, /* .isArray */
+ false /* .isOptional */
+},
+{
+ UA_TYPENAME("SubscriptionIds") /* .memberName */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
+ offsetof(UA_TransferSubscriptionsRequest, subscriptionIdsSize) - offsetof(UA_TransferSubscriptionsRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
+ true, /* .isArray */
+ false /* .isOptional */
+},
+{
+ UA_TYPENAME("SendInitialValues") /* .memberName */
+ &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
+ offsetof(UA_TransferSubscriptionsRequest, sendInitialValues) - offsetof(UA_TransferSubscriptionsRequest, subscriptionIds) - sizeof(void *), /* .padding */
+ false, /* .isArray */
+ false /* .isOptional */
+},};
+
+/* TransferSubscriptionsResponse */
+static UA_DataTypeMember TransferSubscriptionsResponse_members[3] = {
+{
+ UA_TYPENAME("ResponseHeader") /* .memberName */
+ &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
+ 0, /* .padding */
+ false, /* .isArray */
+ false /* .isOptional */
+},
+{
+ UA_TYPENAME("Results") /* .memberName */
+ &UA_TYPES[UA_TYPES_TRANSFERRESULT], /* .memberType */
+ offsetof(UA_TransferSubscriptionsResponse, resultsSize) - offsetof(UA_TransferSubscriptionsResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
+ true, /* .isArray */
+ false /* .isOptional */
+},
+{
+ UA_TYPENAME("DiagnosticInfos") /* .memberName */
+ &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
+ offsetof(UA_TransferSubscriptionsResponse, diagnosticInfosSize) - offsetof(UA_TransferSubscriptionsResponse, results) - sizeof(void *), /* .padding */
+ true, /* .isArray */
+ false /* .isOptional */
},};
/* DeleteSubscriptionsRequest */
static UA_DataTypeMember DeleteSubscriptionsRequest_members[2] = {
{
UA_TYPENAME("RequestHeader") /* .memberName */
- UA_TYPES_REQUESTHEADER, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("SubscriptionIds") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_DeleteSubscriptionsRequest, subscriptionIdsSize) - offsetof(UA_DeleteSubscriptionsRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* DeleteSubscriptionsResponse */
static UA_DataTypeMember DeleteSubscriptionsResponse_members[3] = {
{
UA_TYPENAME("ResponseHeader") /* .memberName */
- UA_TYPES_RESPONSEHEADER, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("Results") /* .memberName */
- UA_TYPES_STATUSCODE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
offsetof(UA_DeleteSubscriptionsResponse, resultsSize) - offsetof(UA_DeleteSubscriptionsResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("DiagnosticInfos") /* .memberName */
- UA_TYPES_DIAGNOSTICINFO, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
offsetof(UA_DeleteSubscriptionsResponse, diagnosticInfosSize) - offsetof(UA_DeleteSubscriptionsResponse, results) - sizeof(void *), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* BuildInfo */
static UA_DataTypeMember BuildInfo_members[6] = {
{
UA_TYPENAME("ProductUri") /* .memberName */
- UA_TYPES_STRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STRING], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("ManufacturerName") /* .memberName */
- UA_TYPES_STRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STRING], /* .memberType */
offsetof(UA_BuildInfo, manufacturerName) - offsetof(UA_BuildInfo, productUri) - sizeof(UA_String), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("ProductName") /* .memberName */
- UA_TYPES_STRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STRING], /* .memberType */
offsetof(UA_BuildInfo, productName) - offsetof(UA_BuildInfo, manufacturerName) - sizeof(UA_String), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("SoftwareVersion") /* .memberName */
- UA_TYPES_STRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STRING], /* .memberType */
offsetof(UA_BuildInfo, softwareVersion) - offsetof(UA_BuildInfo, productName) - sizeof(UA_String), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("BuildNumber") /* .memberName */
- UA_TYPES_STRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STRING], /* .memberType */
offsetof(UA_BuildInfo, buildNumber) - offsetof(UA_BuildInfo, softwareVersion) - sizeof(UA_String), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("BuildDate") /* .memberName */
- UA_TYPES_DATETIME, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */
offsetof(UA_BuildInfo, buildDate) - offsetof(UA_BuildInfo, buildNumber) - sizeof(UA_String), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* RedundancySupport */
@@ -15738,204 +14397,180 @@ static UA_DataTypeMember BuildInfo_members[6] = {
static UA_DataTypeMember ServerDiagnosticsSummaryDataType_members[12] = {
{
UA_TYPENAME("ServerViewCount") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("CurrentSessionCount") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_ServerDiagnosticsSummaryDataType, currentSessionCount) - offsetof(UA_ServerDiagnosticsSummaryDataType, serverViewCount) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("CumulatedSessionCount") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_ServerDiagnosticsSummaryDataType, cumulatedSessionCount) - offsetof(UA_ServerDiagnosticsSummaryDataType, currentSessionCount) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("SecurityRejectedSessionCount") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_ServerDiagnosticsSummaryDataType, securityRejectedSessionCount) - offsetof(UA_ServerDiagnosticsSummaryDataType, cumulatedSessionCount) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("RejectedSessionCount") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_ServerDiagnosticsSummaryDataType, rejectedSessionCount) - offsetof(UA_ServerDiagnosticsSummaryDataType, securityRejectedSessionCount) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("SessionTimeoutCount") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_ServerDiagnosticsSummaryDataType, sessionTimeoutCount) - offsetof(UA_ServerDiagnosticsSummaryDataType, rejectedSessionCount) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("SessionAbortCount") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_ServerDiagnosticsSummaryDataType, sessionAbortCount) - offsetof(UA_ServerDiagnosticsSummaryDataType, sessionTimeoutCount) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("CurrentSubscriptionCount") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_ServerDiagnosticsSummaryDataType, currentSubscriptionCount) - offsetof(UA_ServerDiagnosticsSummaryDataType, sessionAbortCount) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("CumulatedSubscriptionCount") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_ServerDiagnosticsSummaryDataType, cumulatedSubscriptionCount) - offsetof(UA_ServerDiagnosticsSummaryDataType, currentSubscriptionCount) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("PublishingIntervalCount") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_ServerDiagnosticsSummaryDataType, publishingIntervalCount) - offsetof(UA_ServerDiagnosticsSummaryDataType, cumulatedSubscriptionCount) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("SecurityRejectedRequestsCount") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_ServerDiagnosticsSummaryDataType, securityRejectedRequestsCount) - offsetof(UA_ServerDiagnosticsSummaryDataType, publishingIntervalCount) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("RejectedRequestsCount") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_ServerDiagnosticsSummaryDataType, rejectedRequestsCount) - offsetof(UA_ServerDiagnosticsSummaryDataType, securityRejectedRequestsCount) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* ServerStatusDataType */
static UA_DataTypeMember ServerStatusDataType_members[6] = {
{
UA_TYPENAME("StartTime") /* .memberName */
- UA_TYPES_DATETIME, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("CurrentTime") /* .memberName */
- UA_TYPES_DATETIME, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */
offsetof(UA_ServerStatusDataType, currentTime) - offsetof(UA_ServerStatusDataType, startTime) - sizeof(UA_DateTime), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("State") /* .memberName */
- UA_TYPES_SERVERSTATE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_SERVERSTATE], /* .memberType */
offsetof(UA_ServerStatusDataType, state) - offsetof(UA_ServerStatusDataType, currentTime) - sizeof(UA_DateTime), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("BuildInfo") /* .memberName */
- UA_TYPES_BUILDINFO, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_BUILDINFO], /* .memberType */
offsetof(UA_ServerStatusDataType, buildInfo) - offsetof(UA_ServerStatusDataType, state) - sizeof(UA_ServerState), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("SecondsTillShutdown") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_ServerStatusDataType, secondsTillShutdown) - offsetof(UA_ServerStatusDataType, buildInfo) - sizeof(UA_BuildInfo), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("ShutdownReason") /* .memberName */
- UA_TYPES_LOCALIZEDTEXT, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
offsetof(UA_ServerStatusDataType, shutdownReason) - offsetof(UA_ServerStatusDataType, secondsTillShutdown) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* Range */
static UA_DataTypeMember Range_members[2] = {
{
UA_TYPENAME("Low") /* .memberName */
- UA_TYPES_DOUBLE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("High") /* .memberName */
- UA_TYPES_DOUBLE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */
offsetof(UA_Range, high) - offsetof(UA_Range, low) - sizeof(UA_Double), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* EUInformation */
static UA_DataTypeMember EUInformation_members[4] = {
{
UA_TYPENAME("NamespaceUri") /* .memberName */
- UA_TYPES_STRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STRING], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("UnitId") /* .memberName */
- UA_TYPES_INT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_INT32], /* .memberType */
offsetof(UA_EUInformation, unitId) - offsetof(UA_EUInformation, namespaceUri) - sizeof(UA_String), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("DisplayName") /* .memberName */
- UA_TYPES_LOCALIZEDTEXT, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
offsetof(UA_EUInformation, displayName) - offsetof(UA_EUInformation, unitId) - sizeof(UA_Int32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("Description") /* .memberName */
- UA_TYPES_LOCALIZEDTEXT, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
offsetof(UA_EUInformation, description) - offsetof(UA_EUInformation, displayName) - sizeof(UA_LocalizedText), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* AxisScaleEnumeration */
@@ -15945,2989 +14580,2788 @@ static UA_DataTypeMember EUInformation_members[4] = {
static UA_DataTypeMember ComplexNumberType_members[2] = {
{
UA_TYPENAME("Real") /* .memberName */
- UA_TYPES_FLOAT, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_FLOAT], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("Imaginary") /* .memberName */
- UA_TYPES_FLOAT, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_FLOAT], /* .memberType */
offsetof(UA_ComplexNumberType, imaginary) - offsetof(UA_ComplexNumberType, real) - sizeof(UA_Float), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* DoubleComplexNumberType */
static UA_DataTypeMember DoubleComplexNumberType_members[2] = {
{
UA_TYPENAME("Real") /* .memberName */
- UA_TYPES_DOUBLE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("Imaginary") /* .memberName */
- UA_TYPES_DOUBLE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */
offsetof(UA_DoubleComplexNumberType, imaginary) - offsetof(UA_DoubleComplexNumberType, real) - sizeof(UA_Double), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* AxisInformation */
static UA_DataTypeMember AxisInformation_members[5] = {
{
UA_TYPENAME("EngineeringUnits") /* .memberName */
- UA_TYPES_EUINFORMATION, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_EUINFORMATION], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("EURange") /* .memberName */
- UA_TYPES_RANGE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_RANGE], /* .memberType */
offsetof(UA_AxisInformation, eURange) - offsetof(UA_AxisInformation, engineeringUnits) - sizeof(UA_EUInformation), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("Title") /* .memberName */
- UA_TYPES_LOCALIZEDTEXT, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
offsetof(UA_AxisInformation, title) - offsetof(UA_AxisInformation, eURange) - sizeof(UA_Range), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("AxisScaleType") /* .memberName */
- UA_TYPES_AXISSCALEENUMERATION, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_AXISSCALEENUMERATION], /* .memberType */
offsetof(UA_AxisInformation, axisScaleType) - offsetof(UA_AxisInformation, title) - sizeof(UA_LocalizedText), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("AxisSteps") /* .memberName */
- UA_TYPES_DOUBLE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */
offsetof(UA_AxisInformation, axisStepsSize) - offsetof(UA_AxisInformation, axisScaleType) - sizeof(UA_AxisScaleEnumeration), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* XVType */
static UA_DataTypeMember XVType_members[2] = {
{
UA_TYPENAME("X") /* .memberName */
- UA_TYPES_DOUBLE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("Value") /* .memberName */
- UA_TYPES_FLOAT, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_FLOAT], /* .memberType */
offsetof(UA_XVType, value) - offsetof(UA_XVType, x) - sizeof(UA_Double), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* EnumDefinition */
static UA_DataTypeMember EnumDefinition_members[1] = {
{
UA_TYPENAME("Fields") /* .memberName */
- UA_TYPES_ENUMFIELD, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_ENUMFIELD], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* ReadEventDetails */
static UA_DataTypeMember ReadEventDetails_members[4] = {
{
UA_TYPENAME("NumValuesPerNode") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("StartTime") /* .memberName */
- UA_TYPES_DATETIME, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */
offsetof(UA_ReadEventDetails, startTime) - offsetof(UA_ReadEventDetails, numValuesPerNode) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("EndTime") /* .memberName */
- UA_TYPES_DATETIME, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */
offsetof(UA_ReadEventDetails, endTime) - offsetof(UA_ReadEventDetails, startTime) - sizeof(UA_DateTime), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("Filter") /* .memberName */
- UA_TYPES_EVENTFILTER, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_EVENTFILTER], /* .memberType */
offsetof(UA_ReadEventDetails, filter) - offsetof(UA_ReadEventDetails, endTime) - sizeof(UA_DateTime), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* ReadProcessedDetails */
static UA_DataTypeMember ReadProcessedDetails_members[5] = {
{
UA_TYPENAME("StartTime") /* .memberName */
- UA_TYPES_DATETIME, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("EndTime") /* .memberName */
- UA_TYPES_DATETIME, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */
offsetof(UA_ReadProcessedDetails, endTime) - offsetof(UA_ReadProcessedDetails, startTime) - sizeof(UA_DateTime), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("ProcessingInterval") /* .memberName */
- UA_TYPES_DOUBLE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */
offsetof(UA_ReadProcessedDetails, processingInterval) - offsetof(UA_ReadProcessedDetails, endTime) - sizeof(UA_DateTime), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("AggregateType") /* .memberName */
- UA_TYPES_NODEID, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
offsetof(UA_ReadProcessedDetails, aggregateTypeSize) - offsetof(UA_ReadProcessedDetails, processingInterval) - sizeof(UA_Double), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("AggregateConfiguration") /* .memberName */
- UA_TYPES_AGGREGATECONFIGURATION, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_AGGREGATECONFIGURATION], /* .memberType */
offsetof(UA_ReadProcessedDetails, aggregateConfiguration) - offsetof(UA_ReadProcessedDetails, aggregateType) - sizeof(void *), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* ModificationInfo */
static UA_DataTypeMember ModificationInfo_members[3] = {
{
UA_TYPENAME("ModificationTime") /* .memberName */
- UA_TYPES_DATETIME, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("UpdateType") /* .memberName */
- UA_TYPES_HISTORYUPDATETYPE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_HISTORYUPDATETYPE], /* .memberType */
offsetof(UA_ModificationInfo, updateType) - offsetof(UA_ModificationInfo, modificationTime) - sizeof(UA_DateTime), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("UserName") /* .memberName */
- UA_TYPES_STRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STRING], /* .memberType */
offsetof(UA_ModificationInfo, userName) - offsetof(UA_ModificationInfo, updateType) - sizeof(UA_HistoryUpdateType), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* HistoryModifiedData */
static UA_DataTypeMember HistoryModifiedData_members[2] = {
{
UA_TYPENAME("DataValues") /* .memberName */
- UA_TYPES_DATAVALUE, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DATAVALUE], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("ModificationInfos") /* .memberName */
- UA_TYPES_MODIFICATIONINFO, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_MODIFICATIONINFO], /* .memberType */
offsetof(UA_HistoryModifiedData, modificationInfosSize) - offsetof(UA_HistoryModifiedData, dataValues) - sizeof(void *), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* HistoryEvent */
static UA_DataTypeMember HistoryEvent_members[1] = {
{
UA_TYPENAME("Events") /* .memberName */
- UA_TYPES_HISTORYEVENTFIELDLIST, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_HISTORYEVENTFIELDLIST], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* DataChangeNotification */
static UA_DataTypeMember DataChangeNotification_members[2] = {
{
UA_TYPENAME("MonitoredItems") /* .memberName */
- UA_TYPES_MONITOREDITEMNOTIFICATION, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_MONITOREDITEMNOTIFICATION], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("DiagnosticInfos") /* .memberName */
- UA_TYPES_DIAGNOSTICINFO, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
offsetof(UA_DataChangeNotification, diagnosticInfosSize) - offsetof(UA_DataChangeNotification, monitoredItems) - sizeof(void *), /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* EventNotificationList */
static UA_DataTypeMember EventNotificationList_members[1] = {
{
UA_TYPENAME("Events") /* .memberName */
- UA_TYPES_EVENTFIELDLIST, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_EVENTFIELDLIST], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
true, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
const UA_DataType UA_TYPES[UA_TYPES_COUNT] = {
/* Boolean */
{
UA_TYPENAME("Boolean") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {1}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {1LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
sizeof(UA_Boolean), /* .memSize */
- UA_TYPES_BOOLEAN, /* .typeIndex */
UA_DATATYPEKIND_BOOLEAN, /* .typeKind */
true, /* .pointerFree */
- true, /* .overlayable */
+ false, /* .overlayable */
0, /* .membersSize */
- 0, /* .binaryEncodingId */
- Boolean_members /* .members */
+ Boolean_members /* .members */
},
/* SByte */
{
UA_TYPENAME("SByte") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {2}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {2LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
sizeof(UA_SByte), /* .memSize */
- UA_TYPES_SBYTE, /* .typeIndex */
UA_DATATYPEKIND_SBYTE, /* .typeKind */
true, /* .pointerFree */
true, /* .overlayable */
0, /* .membersSize */
- 0, /* .binaryEncodingId */
- SByte_members /* .members */
+ SByte_members /* .members */
},
/* Byte */
{
UA_TYPENAME("Byte") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {3}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {3LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
sizeof(UA_Byte), /* .memSize */
- UA_TYPES_BYTE, /* .typeIndex */
UA_DATATYPEKIND_BYTE, /* .typeKind */
true, /* .pointerFree */
true, /* .overlayable */
0, /* .membersSize */
- 0, /* .binaryEncodingId */
- Byte_members /* .members */
+ Byte_members /* .members */
},
/* Int16 */
{
UA_TYPENAME("Int16") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {4}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {4LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
sizeof(UA_Int16), /* .memSize */
- UA_TYPES_INT16, /* .typeIndex */
UA_DATATYPEKIND_INT16, /* .typeKind */
true, /* .pointerFree */
UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
0, /* .membersSize */
- 0, /* .binaryEncodingId */
- Int16_members /* .members */
+ Int16_members /* .members */
},
/* UInt16 */
{
UA_TYPENAME("UInt16") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {5}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {5LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
sizeof(UA_UInt16), /* .memSize */
- UA_TYPES_UINT16, /* .typeIndex */
UA_DATATYPEKIND_UINT16, /* .typeKind */
true, /* .pointerFree */
UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
0, /* .membersSize */
- 0, /* .binaryEncodingId */
- UInt16_members /* .members */
+ UInt16_members /* .members */
},
/* Int32 */
{
UA_TYPENAME("Int32") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {6}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {6LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
sizeof(UA_Int32), /* .memSize */
- UA_TYPES_INT32, /* .typeIndex */
UA_DATATYPEKIND_INT32, /* .typeKind */
true, /* .pointerFree */
UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
0, /* .membersSize */
- 0, /* .binaryEncodingId */
- Int32_members /* .members */
+ Int32_members /* .members */
},
/* UInt32 */
{
UA_TYPENAME("UInt32") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {7}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {7LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
sizeof(UA_UInt32), /* .memSize */
- UA_TYPES_UINT32, /* .typeIndex */
UA_DATATYPEKIND_UINT32, /* .typeKind */
true, /* .pointerFree */
UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
0, /* .membersSize */
- 0, /* .binaryEncodingId */
- UInt32_members /* .members */
+ UInt32_members /* .members */
},
/* Int64 */
{
UA_TYPENAME("Int64") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {8}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {8LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
sizeof(UA_Int64), /* .memSize */
- UA_TYPES_INT64, /* .typeIndex */
UA_DATATYPEKIND_INT64, /* .typeKind */
true, /* .pointerFree */
UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
0, /* .membersSize */
- 0, /* .binaryEncodingId */
- Int64_members /* .members */
+ Int64_members /* .members */
},
/* UInt64 */
{
UA_TYPENAME("UInt64") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {9}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {9LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
sizeof(UA_UInt64), /* .memSize */
- UA_TYPES_UINT64, /* .typeIndex */
UA_DATATYPEKIND_UINT64, /* .typeKind */
true, /* .pointerFree */
UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
0, /* .membersSize */
- 0, /* .binaryEncodingId */
- UInt64_members /* .members */
+ UInt64_members /* .members */
},
/* Float */
{
UA_TYPENAME("Float") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {10}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {10LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
sizeof(UA_Float), /* .memSize */
- UA_TYPES_FLOAT, /* .typeIndex */
UA_DATATYPEKIND_FLOAT, /* .typeKind */
true, /* .pointerFree */
UA_BINARY_OVERLAYABLE_FLOAT, /* .overlayable */
0, /* .membersSize */
- 0, /* .binaryEncodingId */
- Float_members /* .members */
+ Float_members /* .members */
},
/* Double */
{
UA_TYPENAME("Double") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {11}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {11LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
sizeof(UA_Double), /* .memSize */
- UA_TYPES_DOUBLE, /* .typeIndex */
UA_DATATYPEKIND_DOUBLE, /* .typeKind */
true, /* .pointerFree */
UA_BINARY_OVERLAYABLE_FLOAT, /* .overlayable */
0, /* .membersSize */
- 0, /* .binaryEncodingId */
- Double_members /* .members */
+ Double_members /* .members */
},
/* String */
{
UA_TYPENAME("String") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {12}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {12LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
sizeof(UA_String), /* .memSize */
- UA_TYPES_STRING, /* .typeIndex */
UA_DATATYPEKIND_STRING, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
0, /* .membersSize */
- 0, /* .binaryEncodingId */
- String_members /* .members */
+ String_members /* .members */
},
/* DateTime */
{
UA_TYPENAME("DateTime") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {13}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {13LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
sizeof(UA_DateTime), /* .memSize */
- UA_TYPES_DATETIME, /* .typeIndex */
UA_DATATYPEKIND_DATETIME, /* .typeKind */
true, /* .pointerFree */
UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
0, /* .membersSize */
- 0, /* .binaryEncodingId */
- DateTime_members /* .members */
+ DateTime_members /* .members */
},
/* Guid */
{
UA_TYPENAME("Guid") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {14}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {14LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
sizeof(UA_Guid), /* .memSize */
- UA_TYPES_GUID, /* .typeIndex */
UA_DATATYPEKIND_GUID, /* .typeKind */
true, /* .pointerFree */
(UA_BINARY_OVERLAYABLE_INTEGER && offsetof(UA_Guid, data2) == sizeof(UA_UInt32) && offsetof(UA_Guid, data3) == (sizeof(UA_UInt16) + sizeof(UA_UInt32)) && offsetof(UA_Guid, data4) == (2*sizeof(UA_UInt32))), /* .overlayable */
0, /* .membersSize */
- 0, /* .binaryEncodingId */
- Guid_members /* .members */
+ Guid_members /* .members */
},
/* ByteString */
{
UA_TYPENAME("ByteString") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {15}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {15LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
sizeof(UA_ByteString), /* .memSize */
- UA_TYPES_BYTESTRING, /* .typeIndex */
UA_DATATYPEKIND_BYTESTRING, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
0, /* .membersSize */
- 0, /* .binaryEncodingId */
- ByteString_members /* .members */
+ ByteString_members /* .members */
},
/* XmlElement */
{
UA_TYPENAME("XmlElement") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {16}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {16LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
sizeof(UA_XmlElement), /* .memSize */
- UA_TYPES_XMLELEMENT, /* .typeIndex */
UA_DATATYPEKIND_XMLELEMENT, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
0, /* .membersSize */
- 0, /* .binaryEncodingId */
- XmlElement_members /* .members */
+ XmlElement_members /* .members */
},
/* NodeId */
{
UA_TYPENAME("NodeId") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {17}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {17LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
sizeof(UA_NodeId), /* .memSize */
- UA_TYPES_NODEID, /* .typeIndex */
UA_DATATYPEKIND_NODEID, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
0, /* .membersSize */
- 0, /* .binaryEncodingId */
- NodeId_members /* .members */
+ NodeId_members /* .members */
},
/* ExpandedNodeId */
{
UA_TYPENAME("ExpandedNodeId") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {18}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {18LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
sizeof(UA_ExpandedNodeId), /* .memSize */
- UA_TYPES_EXPANDEDNODEID, /* .typeIndex */
UA_DATATYPEKIND_EXPANDEDNODEID, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
0, /* .membersSize */
- 0, /* .binaryEncodingId */
- ExpandedNodeId_members /* .members */
+ ExpandedNodeId_members /* .members */
},
/* StatusCode */
{
UA_TYPENAME("StatusCode") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {19}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {19LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
sizeof(UA_StatusCode), /* .memSize */
- UA_TYPES_STATUSCODE, /* .typeIndex */
UA_DATATYPEKIND_STATUSCODE, /* .typeKind */
true, /* .pointerFree */
UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
0, /* .membersSize */
- 0, /* .binaryEncodingId */
- StatusCode_members /* .members */
+ StatusCode_members /* .members */
},
/* QualifiedName */
{
UA_TYPENAME("QualifiedName") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {20}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {20LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
sizeof(UA_QualifiedName), /* .memSize */
- UA_TYPES_QUALIFIEDNAME, /* .typeIndex */
UA_DATATYPEKIND_QUALIFIEDNAME, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
0, /* .membersSize */
- 0, /* .binaryEncodingId */
- QualifiedName_members /* .members */
+ QualifiedName_members /* .members */
},
/* LocalizedText */
{
UA_TYPENAME("LocalizedText") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {21}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {21LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
sizeof(UA_LocalizedText), /* .memSize */
- UA_TYPES_LOCALIZEDTEXT, /* .typeIndex */
UA_DATATYPEKIND_LOCALIZEDTEXT, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
0, /* .membersSize */
- 0, /* .binaryEncodingId */
- LocalizedText_members /* .members */
+ LocalizedText_members /* .members */
},
/* ExtensionObject */
{
UA_TYPENAME("ExtensionObject") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {22}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {22LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
sizeof(UA_ExtensionObject), /* .memSize */
- UA_TYPES_EXTENSIONOBJECT, /* .typeIndex */
UA_DATATYPEKIND_EXTENSIONOBJECT, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
0, /* .membersSize */
- 0, /* .binaryEncodingId */
- ExtensionObject_members /* .members */
+ ExtensionObject_members /* .members */
},
/* DataValue */
{
UA_TYPENAME("DataValue") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {23}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {23LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
sizeof(UA_DataValue), /* .memSize */
- UA_TYPES_DATAVALUE, /* .typeIndex */
UA_DATATYPEKIND_DATAVALUE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
0, /* .membersSize */
- 0, /* .binaryEncodingId */
- DataValue_members /* .members */
+ DataValue_members /* .members */
},
/* Variant */
{
UA_TYPENAME("Variant") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {24}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {24LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
sizeof(UA_Variant), /* .memSize */
- UA_TYPES_VARIANT, /* .typeIndex */
UA_DATATYPEKIND_VARIANT, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
0, /* .membersSize */
- 0, /* .binaryEncodingId */
- Variant_members /* .members */
+ Variant_members /* .members */
},
/* DiagnosticInfo */
{
UA_TYPENAME("DiagnosticInfo") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {25}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {25LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
sizeof(UA_DiagnosticInfo), /* .memSize */
- UA_TYPES_DIAGNOSTICINFO, /* .typeIndex */
UA_DATATYPEKIND_DIAGNOSTICINFO, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
0, /* .membersSize */
- 0, /* .binaryEncodingId */
- DiagnosticInfo_members /* .members */
+ DiagnosticInfo_members /* .members */
+},
+/* KeyValuePair */
+{
+ UA_TYPENAME("KeyValuePair") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {14533LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {14846LU}}, /* .binaryEncodingId */
+ sizeof(UA_KeyValuePair), /* .memSize */
+ UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 2, /* .membersSize */
+ KeyValuePair_members /* .members */
},
/* NodeClass */
{
UA_TYPENAME("NodeClass") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {257}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {257LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
sizeof(UA_NodeClass), /* .memSize */
- UA_TYPES_INT32, /* .typeIndex */
UA_DATATYPEKIND_ENUM, /* .typeKind */
true, /* .pointerFree */
UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
0, /* .membersSize */
- 0, /* .binaryEncodingId */
- NodeClass_members /* .members */
+ NodeClass_members /* .members */
},
/* StructureType */
{
UA_TYPENAME("StructureType") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {98}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {98LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
sizeof(UA_StructureType), /* .memSize */
- UA_TYPES_INT32, /* .typeIndex */
UA_DATATYPEKIND_ENUM, /* .typeKind */
true, /* .pointerFree */
UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
0, /* .membersSize */
- 0, /* .binaryEncodingId */
- StructureType_members /* .members */
+ StructureType_members /* .members */
},
/* StructureField */
{
UA_TYPENAME("StructureField") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {101}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {101LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {14844LU}}, /* .binaryEncodingId */
sizeof(UA_StructureField), /* .memSize */
- UA_TYPES_STRUCTUREFIELD, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
7, /* .membersSize */
- 14844, /* .binaryEncodingId */
- StructureField_members /* .members */
+ StructureField_members /* .members */
},
/* StructureDefinition */
{
UA_TYPENAME("StructureDefinition") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {99}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {99LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {122LU}}, /* .binaryEncodingId */
sizeof(UA_StructureDefinition), /* .memSize */
- UA_TYPES_STRUCTUREDEFINITION, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
4, /* .membersSize */
- 122, /* .binaryEncodingId */
- StructureDefinition_members /* .members */
+ StructureDefinition_members /* .members */
},
/* Argument */
{
UA_TYPENAME("Argument") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {296}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {296LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {298LU}}, /* .binaryEncodingId */
sizeof(UA_Argument), /* .memSize */
- UA_TYPES_ARGUMENT, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
5, /* .membersSize */
- 298, /* .binaryEncodingId */
- Argument_members /* .members */
+ Argument_members /* .members */
},
/* EnumValueType */
{
UA_TYPENAME("EnumValueType") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {7594}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {7594LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {8251LU}}, /* .binaryEncodingId */
sizeof(UA_EnumValueType), /* .memSize */
- UA_TYPES_ENUMVALUETYPE, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
3, /* .membersSize */
- 8251, /* .binaryEncodingId */
- EnumValueType_members /* .members */
+ EnumValueType_members /* .members */
},
/* EnumField */
{
UA_TYPENAME("EnumField") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {102}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {102LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {14845LU}}, /* .binaryEncodingId */
sizeof(UA_EnumField), /* .memSize */
- UA_TYPES_ENUMFIELD, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
4, /* .membersSize */
- 14845, /* .binaryEncodingId */
- EnumField_members /* .members */
+ EnumField_members /* .members */
},
/* Duration */
{
UA_TYPENAME("Duration") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {290}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {290LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
sizeof(UA_Duration), /* .memSize */
- UA_TYPES_DURATION, /* .typeIndex */
UA_DATATYPEKIND_DOUBLE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
0, /* .membersSize */
- 0, /* .binaryEncodingId */
- Duration_members /* .members */
+ Duration_members /* .members */
},
/* UtcTime */
{
UA_TYPENAME("UtcTime") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {294}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {294LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
sizeof(UA_UtcTime), /* .memSize */
- UA_TYPES_UTCTIME, /* .typeIndex */
UA_DATATYPEKIND_DATETIME, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
0, /* .membersSize */
- 0, /* .binaryEncodingId */
- UtcTime_members /* .members */
+ UtcTime_members /* .members */
},
/* LocaleId */
{
UA_TYPENAME("LocaleId") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {295}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {295LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
sizeof(UA_LocaleId), /* .memSize */
- UA_TYPES_LOCALEID, /* .typeIndex */
UA_DATATYPEKIND_STRING, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
0, /* .membersSize */
- 0, /* .binaryEncodingId */
- LocaleId_members /* .members */
+ LocaleId_members /* .members */
},
/* TimeZoneDataType */
{
UA_TYPENAME("TimeZoneDataType") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {8912}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {8912LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {8917LU}}, /* .binaryEncodingId */
sizeof(UA_TimeZoneDataType), /* .memSize */
- UA_TYPES_TIMEZONEDATATYPE, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
true, /* .pointerFree */
false, /* .overlayable */
2, /* .membersSize */
- 8917, /* .binaryEncodingId */
- TimeZoneDataType_members /* .members */
+ TimeZoneDataType_members /* .members */
},
/* ApplicationType */
{
UA_TYPENAME("ApplicationType") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {307}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {307LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
sizeof(UA_ApplicationType), /* .memSize */
- UA_TYPES_INT32, /* .typeIndex */
UA_DATATYPEKIND_ENUM, /* .typeKind */
true, /* .pointerFree */
UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
0, /* .membersSize */
- 0, /* .binaryEncodingId */
- ApplicationType_members /* .members */
+ ApplicationType_members /* .members */
},
/* ApplicationDescription */
{
UA_TYPENAME("ApplicationDescription") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {308}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {308LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {310LU}}, /* .binaryEncodingId */
sizeof(UA_ApplicationDescription), /* .memSize */
- UA_TYPES_APPLICATIONDESCRIPTION, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
7, /* .membersSize */
- 310, /* .binaryEncodingId */
- ApplicationDescription_members /* .members */
+ ApplicationDescription_members /* .members */
},
/* RequestHeader */
{
UA_TYPENAME("RequestHeader") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {389}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {389LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {391LU}}, /* .binaryEncodingId */
sizeof(UA_RequestHeader), /* .memSize */
- UA_TYPES_REQUESTHEADER, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
7, /* .membersSize */
- 391, /* .binaryEncodingId */
- RequestHeader_members /* .members */
+ RequestHeader_members /* .members */
},
/* ResponseHeader */
{
UA_TYPENAME("ResponseHeader") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {392}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {392LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {394LU}}, /* .binaryEncodingId */
sizeof(UA_ResponseHeader), /* .memSize */
- UA_TYPES_RESPONSEHEADER, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
6, /* .membersSize */
- 394, /* .binaryEncodingId */
- ResponseHeader_members /* .members */
+ ResponseHeader_members /* .members */
},
/* ServiceFault */
{
UA_TYPENAME("ServiceFault") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {395}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {395LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {397LU}}, /* .binaryEncodingId */
sizeof(UA_ServiceFault), /* .memSize */
- UA_TYPES_SERVICEFAULT, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
1, /* .membersSize */
- 397, /* .binaryEncodingId */
- ServiceFault_members /* .members */
+ ServiceFault_members /* .members */
},
/* FindServersRequest */
{
UA_TYPENAME("FindServersRequest") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {420}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {420LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {422LU}}, /* .binaryEncodingId */
sizeof(UA_FindServersRequest), /* .memSize */
- UA_TYPES_FINDSERVERSREQUEST, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
4, /* .membersSize */
- 422, /* .binaryEncodingId */
- FindServersRequest_members /* .members */
+ FindServersRequest_members /* .members */
},
/* FindServersResponse */
{
UA_TYPENAME("FindServersResponse") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {423}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {423LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {425LU}}, /* .binaryEncodingId */
sizeof(UA_FindServersResponse), /* .memSize */
- UA_TYPES_FINDSERVERSRESPONSE, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
2, /* .membersSize */
- 425, /* .binaryEncodingId */
- FindServersResponse_members /* .members */
+ FindServersResponse_members /* .members */
},
/* MessageSecurityMode */
{
UA_TYPENAME("MessageSecurityMode") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {302}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {302LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
sizeof(UA_MessageSecurityMode), /* .memSize */
- UA_TYPES_INT32, /* .typeIndex */
UA_DATATYPEKIND_ENUM, /* .typeKind */
true, /* .pointerFree */
UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
0, /* .membersSize */
- 0, /* .binaryEncodingId */
- MessageSecurityMode_members /* .members */
+ MessageSecurityMode_members /* .members */
},
/* UserTokenType */
{
UA_TYPENAME("UserTokenType") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {303}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {303LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
sizeof(UA_UserTokenType), /* .memSize */
- UA_TYPES_INT32, /* .typeIndex */
UA_DATATYPEKIND_ENUM, /* .typeKind */
true, /* .pointerFree */
UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
0, /* .membersSize */
- 0, /* .binaryEncodingId */
- UserTokenType_members /* .members */
+ UserTokenType_members /* .members */
},
/* UserTokenPolicy */
{
UA_TYPENAME("UserTokenPolicy") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {304}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {304LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {306LU}}, /* .binaryEncodingId */
sizeof(UA_UserTokenPolicy), /* .memSize */
- UA_TYPES_USERTOKENPOLICY, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
5, /* .membersSize */
- 306, /* .binaryEncodingId */
- UserTokenPolicy_members /* .members */
+ UserTokenPolicy_members /* .members */
},
/* EndpointDescription */
{
UA_TYPENAME("EndpointDescription") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {312}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {312LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {314LU}}, /* .binaryEncodingId */
sizeof(UA_EndpointDescription), /* .memSize */
- UA_TYPES_ENDPOINTDESCRIPTION, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
8, /* .membersSize */
- 314, /* .binaryEncodingId */
- EndpointDescription_members /* .members */
+ EndpointDescription_members /* .members */
},
/* GetEndpointsRequest */
{
UA_TYPENAME("GetEndpointsRequest") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {426}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {426LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {428LU}}, /* .binaryEncodingId */
sizeof(UA_GetEndpointsRequest), /* .memSize */
- UA_TYPES_GETENDPOINTSREQUEST, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
4, /* .membersSize */
- 428, /* .binaryEncodingId */
- GetEndpointsRequest_members /* .members */
+ GetEndpointsRequest_members /* .members */
},
/* GetEndpointsResponse */
{
UA_TYPENAME("GetEndpointsResponse") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {429}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {429LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {431LU}}, /* .binaryEncodingId */
sizeof(UA_GetEndpointsResponse), /* .memSize */
- UA_TYPES_GETENDPOINTSRESPONSE, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
2, /* .membersSize */
- 431, /* .binaryEncodingId */
- GetEndpointsResponse_members /* .members */
+ GetEndpointsResponse_members /* .members */
},
/* SecurityTokenRequestType */
{
UA_TYPENAME("SecurityTokenRequestType") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {315}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {315LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
sizeof(UA_SecurityTokenRequestType), /* .memSize */
- UA_TYPES_INT32, /* .typeIndex */
UA_DATATYPEKIND_ENUM, /* .typeKind */
true, /* .pointerFree */
UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
0, /* .membersSize */
- 0, /* .binaryEncodingId */
- SecurityTokenRequestType_members /* .members */
+ SecurityTokenRequestType_members /* .members */
},
/* ChannelSecurityToken */
{
UA_TYPENAME("ChannelSecurityToken") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {441}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {441LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {443LU}}, /* .binaryEncodingId */
sizeof(UA_ChannelSecurityToken), /* .memSize */
- UA_TYPES_CHANNELSECURITYTOKEN, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
true, /* .pointerFree */
false, /* .overlayable */
4, /* .membersSize */
- 443, /* .binaryEncodingId */
- ChannelSecurityToken_members /* .members */
+ ChannelSecurityToken_members /* .members */
},
/* OpenSecureChannelRequest */
{
UA_TYPENAME("OpenSecureChannelRequest") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {444}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {444LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {446LU}}, /* .binaryEncodingId */
sizeof(UA_OpenSecureChannelRequest), /* .memSize */
- UA_TYPES_OPENSECURECHANNELREQUEST, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
6, /* .membersSize */
- 446, /* .binaryEncodingId */
- OpenSecureChannelRequest_members /* .members */
+ OpenSecureChannelRequest_members /* .members */
},
/* OpenSecureChannelResponse */
{
UA_TYPENAME("OpenSecureChannelResponse") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {447}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {447LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {449LU}}, /* .binaryEncodingId */
sizeof(UA_OpenSecureChannelResponse), /* .memSize */
- UA_TYPES_OPENSECURECHANNELRESPONSE, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
4, /* .membersSize */
- 449, /* .binaryEncodingId */
- OpenSecureChannelResponse_members /* .members */
+ OpenSecureChannelResponse_members /* .members */
},
/* CloseSecureChannelRequest */
{
UA_TYPENAME("CloseSecureChannelRequest") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {450}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {450LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {452LU}}, /* .binaryEncodingId */
sizeof(UA_CloseSecureChannelRequest), /* .memSize */
- UA_TYPES_CLOSESECURECHANNELREQUEST, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
1, /* .membersSize */
- 452, /* .binaryEncodingId */
- CloseSecureChannelRequest_members /* .members */
+ CloseSecureChannelRequest_members /* .members */
},
/* CloseSecureChannelResponse */
{
UA_TYPENAME("CloseSecureChannelResponse") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {453}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {453LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {455LU}}, /* .binaryEncodingId */
sizeof(UA_CloseSecureChannelResponse), /* .memSize */
- UA_TYPES_CLOSESECURECHANNELRESPONSE, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
1, /* .membersSize */
- 455, /* .binaryEncodingId */
- CloseSecureChannelResponse_members /* .members */
+ CloseSecureChannelResponse_members /* .members */
},
/* SignedSoftwareCertificate */
{
UA_TYPENAME("SignedSoftwareCertificate") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {344}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {344LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {346LU}}, /* .binaryEncodingId */
sizeof(UA_SignedSoftwareCertificate), /* .memSize */
- UA_TYPES_SIGNEDSOFTWARECERTIFICATE, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
2, /* .membersSize */
- 346, /* .binaryEncodingId */
- SignedSoftwareCertificate_members /* .members */
+ SignedSoftwareCertificate_members /* .members */
},
/* SignatureData */
{
UA_TYPENAME("SignatureData") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {456}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {456LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {458LU}}, /* .binaryEncodingId */
sizeof(UA_SignatureData), /* .memSize */
- UA_TYPES_SIGNATUREDATA, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
2, /* .membersSize */
- 458, /* .binaryEncodingId */
- SignatureData_members /* .members */
+ SignatureData_members /* .members */
},
/* CreateSessionRequest */
{
UA_TYPENAME("CreateSessionRequest") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {459}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {459LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {461LU}}, /* .binaryEncodingId */
sizeof(UA_CreateSessionRequest), /* .memSize */
- UA_TYPES_CREATESESSIONREQUEST, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
9, /* .membersSize */
- 461, /* .binaryEncodingId */
- CreateSessionRequest_members /* .members */
+ CreateSessionRequest_members /* .members */
},
/* CreateSessionResponse */
{
UA_TYPENAME("CreateSessionResponse") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {462}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {462LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {464LU}}, /* .binaryEncodingId */
sizeof(UA_CreateSessionResponse), /* .memSize */
- UA_TYPES_CREATESESSIONRESPONSE, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
10, /* .membersSize */
- 464, /* .binaryEncodingId */
- CreateSessionResponse_members /* .members */
+ CreateSessionResponse_members /* .members */
},
/* UserIdentityToken */
{
UA_TYPENAME("UserIdentityToken") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {316}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {316LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {318LU}}, /* .binaryEncodingId */
sizeof(UA_UserIdentityToken), /* .memSize */
- UA_TYPES_USERIDENTITYTOKEN, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
1, /* .membersSize */
- 318, /* .binaryEncodingId */
- UserIdentityToken_members /* .members */
+ UserIdentityToken_members /* .members */
},
/* AnonymousIdentityToken */
{
UA_TYPENAME("AnonymousIdentityToken") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {319}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {319LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {321LU}}, /* .binaryEncodingId */
sizeof(UA_AnonymousIdentityToken), /* .memSize */
- UA_TYPES_ANONYMOUSIDENTITYTOKEN, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
1, /* .membersSize */
- 321, /* .binaryEncodingId */
- AnonymousIdentityToken_members /* .members */
+ AnonymousIdentityToken_members /* .members */
},
/* UserNameIdentityToken */
{
UA_TYPENAME("UserNameIdentityToken") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {322}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {322LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {324LU}}, /* .binaryEncodingId */
sizeof(UA_UserNameIdentityToken), /* .memSize */
- UA_TYPES_USERNAMEIDENTITYTOKEN, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
4, /* .membersSize */
- 324, /* .binaryEncodingId */
- UserNameIdentityToken_members /* .members */
+ UserNameIdentityToken_members /* .members */
},
/* X509IdentityToken */
{
UA_TYPENAME("X509IdentityToken") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {325}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {325LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {327LU}}, /* .binaryEncodingId */
sizeof(UA_X509IdentityToken), /* .memSize */
- UA_TYPES_X509IDENTITYTOKEN, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
2, /* .membersSize */
- 327, /* .binaryEncodingId */
- X509IdentityToken_members /* .members */
+ X509IdentityToken_members /* .members */
},
/* IssuedIdentityToken */
{
UA_TYPENAME("IssuedIdentityToken") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {938}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {938LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {940LU}}, /* .binaryEncodingId */
sizeof(UA_IssuedIdentityToken), /* .memSize */
- UA_TYPES_ISSUEDIDENTITYTOKEN, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
3, /* .membersSize */
- 940, /* .binaryEncodingId */
- IssuedIdentityToken_members /* .members */
+ IssuedIdentityToken_members /* .members */
},
/* ActivateSessionRequest */
{
UA_TYPENAME("ActivateSessionRequest") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {465}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {465LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {467LU}}, /* .binaryEncodingId */
sizeof(UA_ActivateSessionRequest), /* .memSize */
- UA_TYPES_ACTIVATESESSIONREQUEST, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
6, /* .membersSize */
- 467, /* .binaryEncodingId */
- ActivateSessionRequest_members /* .members */
+ ActivateSessionRequest_members /* .members */
},
/* ActivateSessionResponse */
{
UA_TYPENAME("ActivateSessionResponse") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {468}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {468LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {470LU}}, /* .binaryEncodingId */
sizeof(UA_ActivateSessionResponse), /* .memSize */
- UA_TYPES_ACTIVATESESSIONRESPONSE, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
4, /* .membersSize */
- 470, /* .binaryEncodingId */
- ActivateSessionResponse_members /* .members */
+ ActivateSessionResponse_members /* .members */
},
/* CloseSessionRequest */
{
UA_TYPENAME("CloseSessionRequest") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {471}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {471LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {473LU}}, /* .binaryEncodingId */
sizeof(UA_CloseSessionRequest), /* .memSize */
- UA_TYPES_CLOSESESSIONREQUEST, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
2, /* .membersSize */
- 473, /* .binaryEncodingId */
- CloseSessionRequest_members /* .members */
+ CloseSessionRequest_members /* .members */
},
/* CloseSessionResponse */
{
UA_TYPENAME("CloseSessionResponse") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {474}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {474LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {476LU}}, /* .binaryEncodingId */
sizeof(UA_CloseSessionResponse), /* .memSize */
- UA_TYPES_CLOSESESSIONRESPONSE, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
1, /* .membersSize */
- 476, /* .binaryEncodingId */
- CloseSessionResponse_members /* .members */
+ CloseSessionResponse_members /* .members */
},
/* NodeAttributesMask */
{
UA_TYPENAME("NodeAttributesMask") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {348}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {348LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
sizeof(UA_NodeAttributesMask), /* .memSize */
- UA_TYPES_INT32, /* .typeIndex */
UA_DATATYPEKIND_ENUM, /* .typeKind */
true, /* .pointerFree */
UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
0, /* .membersSize */
- 0, /* .binaryEncodingId */
- NodeAttributesMask_members /* .members */
+ NodeAttributesMask_members /* .members */
},
/* NodeAttributes */
{
UA_TYPENAME("NodeAttributes") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {349}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {349LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {351LU}}, /* .binaryEncodingId */
sizeof(UA_NodeAttributes), /* .memSize */
- UA_TYPES_NODEATTRIBUTES, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
5, /* .membersSize */
- 351, /* .binaryEncodingId */
- NodeAttributes_members /* .members */
+ NodeAttributes_members /* .members */
},
/* ObjectAttributes */
{
UA_TYPENAME("ObjectAttributes") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {352}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {352LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {354LU}}, /* .binaryEncodingId */
sizeof(UA_ObjectAttributes), /* .memSize */
- UA_TYPES_OBJECTATTRIBUTES, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
6, /* .membersSize */
- 354, /* .binaryEncodingId */
- ObjectAttributes_members /* .members */
+ ObjectAttributes_members /* .members */
},
/* VariableAttributes */
{
UA_TYPENAME("VariableAttributes") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {355}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {355LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {357LU}}, /* .binaryEncodingId */
sizeof(UA_VariableAttributes), /* .memSize */
- UA_TYPES_VARIABLEATTRIBUTES, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
13, /* .membersSize */
- 357, /* .binaryEncodingId */
- VariableAttributes_members /* .members */
+ VariableAttributes_members /* .members */
},
/* MethodAttributes */
{
UA_TYPENAME("MethodAttributes") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {358}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {358LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {360LU}}, /* .binaryEncodingId */
sizeof(UA_MethodAttributes), /* .memSize */
- UA_TYPES_METHODATTRIBUTES, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
7, /* .membersSize */
- 360, /* .binaryEncodingId */
- MethodAttributes_members /* .members */
+ MethodAttributes_members /* .members */
},
/* ObjectTypeAttributes */
{
UA_TYPENAME("ObjectTypeAttributes") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {361}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {361LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {363LU}}, /* .binaryEncodingId */
sizeof(UA_ObjectTypeAttributes), /* .memSize */
- UA_TYPES_OBJECTTYPEATTRIBUTES, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
6, /* .membersSize */
- 363, /* .binaryEncodingId */
- ObjectTypeAttributes_members /* .members */
+ ObjectTypeAttributes_members /* .members */
},
/* VariableTypeAttributes */
{
UA_TYPENAME("VariableTypeAttributes") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {364}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {364LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {366LU}}, /* .binaryEncodingId */
sizeof(UA_VariableTypeAttributes), /* .memSize */
- UA_TYPES_VARIABLETYPEATTRIBUTES, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
10, /* .membersSize */
- 366, /* .binaryEncodingId */
- VariableTypeAttributes_members /* .members */
+ VariableTypeAttributes_members /* .members */
},
/* ReferenceTypeAttributes */
{
UA_TYPENAME("ReferenceTypeAttributes") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {367}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {367LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {369LU}}, /* .binaryEncodingId */
sizeof(UA_ReferenceTypeAttributes), /* .memSize */
- UA_TYPES_REFERENCETYPEATTRIBUTES, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
8, /* .membersSize */
- 369, /* .binaryEncodingId */
- ReferenceTypeAttributes_members /* .members */
+ ReferenceTypeAttributes_members /* .members */
},
/* DataTypeAttributes */
{
UA_TYPENAME("DataTypeAttributes") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {370}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {370LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {372LU}}, /* .binaryEncodingId */
sizeof(UA_DataTypeAttributes), /* .memSize */
- UA_TYPES_DATATYPEATTRIBUTES, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
6, /* .membersSize */
- 372, /* .binaryEncodingId */
- DataTypeAttributes_members /* .members */
+ DataTypeAttributes_members /* .members */
},
/* ViewAttributes */
{
UA_TYPENAME("ViewAttributes") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {373}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {373LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {375LU}}, /* .binaryEncodingId */
sizeof(UA_ViewAttributes), /* .memSize */
- UA_TYPES_VIEWATTRIBUTES, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
7, /* .membersSize */
- 375, /* .binaryEncodingId */
- ViewAttributes_members /* .members */
+ ViewAttributes_members /* .members */
},
/* AddNodesItem */
{
UA_TYPENAME("AddNodesItem") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {376}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {376LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {378LU}}, /* .binaryEncodingId */
sizeof(UA_AddNodesItem), /* .memSize */
- UA_TYPES_ADDNODESITEM, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
7, /* .membersSize */
- 378, /* .binaryEncodingId */
- AddNodesItem_members /* .members */
+ AddNodesItem_members /* .members */
},
/* AddNodesResult */
{
UA_TYPENAME("AddNodesResult") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {483}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {483LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {485LU}}, /* .binaryEncodingId */
sizeof(UA_AddNodesResult), /* .memSize */
- UA_TYPES_ADDNODESRESULT, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
2, /* .membersSize */
- 485, /* .binaryEncodingId */
- AddNodesResult_members /* .members */
+ AddNodesResult_members /* .members */
},
/* AddNodesRequest */
{
UA_TYPENAME("AddNodesRequest") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {486}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {486LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {488LU}}, /* .binaryEncodingId */
sizeof(UA_AddNodesRequest), /* .memSize */
- UA_TYPES_ADDNODESREQUEST, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
2, /* .membersSize */
- 488, /* .binaryEncodingId */
- AddNodesRequest_members /* .members */
+ AddNodesRequest_members /* .members */
},
/* AddNodesResponse */
{
UA_TYPENAME("AddNodesResponse") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {489}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {489LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {491LU}}, /* .binaryEncodingId */
sizeof(UA_AddNodesResponse), /* .memSize */
- UA_TYPES_ADDNODESRESPONSE, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
3, /* .membersSize */
- 491, /* .binaryEncodingId */
- AddNodesResponse_members /* .members */
+ AddNodesResponse_members /* .members */
},
/* AddReferencesItem */
{
UA_TYPENAME("AddReferencesItem") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {379}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {379LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {381LU}}, /* .binaryEncodingId */
sizeof(UA_AddReferencesItem), /* .memSize */
- UA_TYPES_ADDREFERENCESITEM, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
6, /* .membersSize */
- 381, /* .binaryEncodingId */
- AddReferencesItem_members /* .members */
+ AddReferencesItem_members /* .members */
},
/* AddReferencesRequest */
{
UA_TYPENAME("AddReferencesRequest") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {492}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {492LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {494LU}}, /* .binaryEncodingId */
sizeof(UA_AddReferencesRequest), /* .memSize */
- UA_TYPES_ADDREFERENCESREQUEST, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
2, /* .membersSize */
- 494, /* .binaryEncodingId */
- AddReferencesRequest_members /* .members */
+ AddReferencesRequest_members /* .members */
},
/* AddReferencesResponse */
{
UA_TYPENAME("AddReferencesResponse") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {495}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {495LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {497LU}}, /* .binaryEncodingId */
sizeof(UA_AddReferencesResponse), /* .memSize */
- UA_TYPES_ADDREFERENCESRESPONSE, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
3, /* .membersSize */
- 497, /* .binaryEncodingId */
- AddReferencesResponse_members /* .members */
+ AddReferencesResponse_members /* .members */
},
/* DeleteNodesItem */
{
UA_TYPENAME("DeleteNodesItem") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {382}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {382LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {384LU}}, /* .binaryEncodingId */
sizeof(UA_DeleteNodesItem), /* .memSize */
- UA_TYPES_DELETENODESITEM, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
2, /* .membersSize */
- 384, /* .binaryEncodingId */
- DeleteNodesItem_members /* .members */
+ DeleteNodesItem_members /* .members */
},
/* DeleteNodesRequest */
{
UA_TYPENAME("DeleteNodesRequest") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {498}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {498LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {500LU}}, /* .binaryEncodingId */
sizeof(UA_DeleteNodesRequest), /* .memSize */
- UA_TYPES_DELETENODESREQUEST, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
2, /* .membersSize */
- 500, /* .binaryEncodingId */
- DeleteNodesRequest_members /* .members */
+ DeleteNodesRequest_members /* .members */
},
/* DeleteNodesResponse */
{
UA_TYPENAME("DeleteNodesResponse") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {501}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {501LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {503LU}}, /* .binaryEncodingId */
sizeof(UA_DeleteNodesResponse), /* .memSize */
- UA_TYPES_DELETENODESRESPONSE, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
3, /* .membersSize */
- 503, /* .binaryEncodingId */
- DeleteNodesResponse_members /* .members */
+ DeleteNodesResponse_members /* .members */
},
/* DeleteReferencesItem */
{
UA_TYPENAME("DeleteReferencesItem") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {385}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {385LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {387LU}}, /* .binaryEncodingId */
sizeof(UA_DeleteReferencesItem), /* .memSize */
- UA_TYPES_DELETEREFERENCESITEM, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
5, /* .membersSize */
- 387, /* .binaryEncodingId */
- DeleteReferencesItem_members /* .members */
+ DeleteReferencesItem_members /* .members */
},
/* DeleteReferencesRequest */
{
UA_TYPENAME("DeleteReferencesRequest") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {504}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {504LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {506LU}}, /* .binaryEncodingId */
sizeof(UA_DeleteReferencesRequest), /* .memSize */
- UA_TYPES_DELETEREFERENCESREQUEST, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
2, /* .membersSize */
- 506, /* .binaryEncodingId */
- DeleteReferencesRequest_members /* .members */
+ DeleteReferencesRequest_members /* .members */
},
/* DeleteReferencesResponse */
{
UA_TYPENAME("DeleteReferencesResponse") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {507}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {507LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {509LU}}, /* .binaryEncodingId */
sizeof(UA_DeleteReferencesResponse), /* .memSize */
- UA_TYPES_DELETEREFERENCESRESPONSE, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
3, /* .membersSize */
- 509, /* .binaryEncodingId */
- DeleteReferencesResponse_members /* .members */
+ DeleteReferencesResponse_members /* .members */
},
/* BrowseDirection */
{
UA_TYPENAME("BrowseDirection") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {510}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {510LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
sizeof(UA_BrowseDirection), /* .memSize */
- UA_TYPES_INT32, /* .typeIndex */
UA_DATATYPEKIND_ENUM, /* .typeKind */
true, /* .pointerFree */
UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
0, /* .membersSize */
- 0, /* .binaryEncodingId */
- BrowseDirection_members /* .members */
+ BrowseDirection_members /* .members */
},
/* ViewDescription */
{
UA_TYPENAME("ViewDescription") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {511}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {511LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {513LU}}, /* .binaryEncodingId */
sizeof(UA_ViewDescription), /* .memSize */
- UA_TYPES_VIEWDESCRIPTION, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
3, /* .membersSize */
- 513, /* .binaryEncodingId */
- ViewDescription_members /* .members */
+ ViewDescription_members /* .members */
},
/* BrowseDescription */
{
UA_TYPENAME("BrowseDescription") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {514}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {514LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {516LU}}, /* .binaryEncodingId */
sizeof(UA_BrowseDescription), /* .memSize */
- UA_TYPES_BROWSEDESCRIPTION, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
6, /* .membersSize */
- 516, /* .binaryEncodingId */
- BrowseDescription_members /* .members */
+ BrowseDescription_members /* .members */
},
/* BrowseResultMask */
{
UA_TYPENAME("BrowseResultMask") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {517}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {517LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
sizeof(UA_BrowseResultMask), /* .memSize */
- UA_TYPES_INT32, /* .typeIndex */
UA_DATATYPEKIND_ENUM, /* .typeKind */
true, /* .pointerFree */
UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
0, /* .membersSize */
- 0, /* .binaryEncodingId */
- BrowseResultMask_members /* .members */
+ BrowseResultMask_members /* .members */
},
/* ReferenceDescription */
{
UA_TYPENAME("ReferenceDescription") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {518}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {518LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {520LU}}, /* .binaryEncodingId */
sizeof(UA_ReferenceDescription), /* .memSize */
- UA_TYPES_REFERENCEDESCRIPTION, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
7, /* .membersSize */
- 520, /* .binaryEncodingId */
- ReferenceDescription_members /* .members */
+ ReferenceDescription_members /* .members */
},
/* BrowseResult */
{
UA_TYPENAME("BrowseResult") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {522}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {522LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {524LU}}, /* .binaryEncodingId */
sizeof(UA_BrowseResult), /* .memSize */
- UA_TYPES_BROWSERESULT, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
3, /* .membersSize */
- 524, /* .binaryEncodingId */
- BrowseResult_members /* .members */
+ BrowseResult_members /* .members */
},
/* BrowseRequest */
{
UA_TYPENAME("BrowseRequest") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {525}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {525LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {527LU}}, /* .binaryEncodingId */
sizeof(UA_BrowseRequest), /* .memSize */
- UA_TYPES_BROWSEREQUEST, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
4, /* .membersSize */
- 527, /* .binaryEncodingId */
- BrowseRequest_members /* .members */
+ BrowseRequest_members /* .members */
},
/* BrowseResponse */
{
UA_TYPENAME("BrowseResponse") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {528}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {528LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {530LU}}, /* .binaryEncodingId */
sizeof(UA_BrowseResponse), /* .memSize */
- UA_TYPES_BROWSERESPONSE, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
3, /* .membersSize */
- 530, /* .binaryEncodingId */
- BrowseResponse_members /* .members */
+ BrowseResponse_members /* .members */
},
/* BrowseNextRequest */
{
UA_TYPENAME("BrowseNextRequest") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {531}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {531LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {533LU}}, /* .binaryEncodingId */
sizeof(UA_BrowseNextRequest), /* .memSize */
- UA_TYPES_BROWSENEXTREQUEST, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
3, /* .membersSize */
- 533, /* .binaryEncodingId */
- BrowseNextRequest_members /* .members */
+ BrowseNextRequest_members /* .members */
},
/* BrowseNextResponse */
{
UA_TYPENAME("BrowseNextResponse") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {534}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {534LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {536LU}}, /* .binaryEncodingId */
sizeof(UA_BrowseNextResponse), /* .memSize */
- UA_TYPES_BROWSENEXTRESPONSE, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
3, /* .membersSize */
- 536, /* .binaryEncodingId */
- BrowseNextResponse_members /* .members */
+ BrowseNextResponse_members /* .members */
},
/* RelativePathElement */
{
UA_TYPENAME("RelativePathElement") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {537}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {537LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {539LU}}, /* .binaryEncodingId */
sizeof(UA_RelativePathElement), /* .memSize */
- UA_TYPES_RELATIVEPATHELEMENT, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
4, /* .membersSize */
- 539, /* .binaryEncodingId */
- RelativePathElement_members /* .members */
+ RelativePathElement_members /* .members */
},
/* RelativePath */
{
UA_TYPENAME("RelativePath") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {540}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {540LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {542LU}}, /* .binaryEncodingId */
sizeof(UA_RelativePath), /* .memSize */
- UA_TYPES_RELATIVEPATH, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
1, /* .membersSize */
- 542, /* .binaryEncodingId */
- RelativePath_members /* .members */
+ RelativePath_members /* .members */
},
/* BrowsePath */
{
UA_TYPENAME("BrowsePath") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {543}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {543LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {545LU}}, /* .binaryEncodingId */
sizeof(UA_BrowsePath), /* .memSize */
- UA_TYPES_BROWSEPATH, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
2, /* .membersSize */
- 545, /* .binaryEncodingId */
- BrowsePath_members /* .members */
+ BrowsePath_members /* .members */
},
/* BrowsePathTarget */
{
UA_TYPENAME("BrowsePathTarget") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {546}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {546LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {548LU}}, /* .binaryEncodingId */
sizeof(UA_BrowsePathTarget), /* .memSize */
- UA_TYPES_BROWSEPATHTARGET, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
2, /* .membersSize */
- 548, /* .binaryEncodingId */
- BrowsePathTarget_members /* .members */
+ BrowsePathTarget_members /* .members */
},
/* BrowsePathResult */
{
UA_TYPENAME("BrowsePathResult") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {549}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {549LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {551LU}}, /* .binaryEncodingId */
sizeof(UA_BrowsePathResult), /* .memSize */
- UA_TYPES_BROWSEPATHRESULT, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
2, /* .membersSize */
- 551, /* .binaryEncodingId */
- BrowsePathResult_members /* .members */
+ BrowsePathResult_members /* .members */
},
/* TranslateBrowsePathsToNodeIdsRequest */
{
UA_TYPENAME("TranslateBrowsePathsToNodeIdsRequest") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {552}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {552LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {554LU}}, /* .binaryEncodingId */
sizeof(UA_TranslateBrowsePathsToNodeIdsRequest), /* .memSize */
- UA_TYPES_TRANSLATEBROWSEPATHSTONODEIDSREQUEST, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
2, /* .membersSize */
- 554, /* .binaryEncodingId */
- TranslateBrowsePathsToNodeIdsRequest_members /* .members */
+ TranslateBrowsePathsToNodeIdsRequest_members /* .members */
},
/* TranslateBrowsePathsToNodeIdsResponse */
{
UA_TYPENAME("TranslateBrowsePathsToNodeIdsResponse") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {555}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {555LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {557LU}}, /* .binaryEncodingId */
sizeof(UA_TranslateBrowsePathsToNodeIdsResponse), /* .memSize */
- UA_TYPES_TRANSLATEBROWSEPATHSTONODEIDSRESPONSE, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
3, /* .membersSize */
- 557, /* .binaryEncodingId */
- TranslateBrowsePathsToNodeIdsResponse_members /* .members */
+ TranslateBrowsePathsToNodeIdsResponse_members /* .members */
},
/* RegisterNodesRequest */
{
UA_TYPENAME("RegisterNodesRequest") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {558}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {558LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {560LU}}, /* .binaryEncodingId */
sizeof(UA_RegisterNodesRequest), /* .memSize */
- UA_TYPES_REGISTERNODESREQUEST, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
2, /* .membersSize */
- 560, /* .binaryEncodingId */
- RegisterNodesRequest_members /* .members */
+ RegisterNodesRequest_members /* .members */
},
/* RegisterNodesResponse */
{
UA_TYPENAME("RegisterNodesResponse") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {561}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {561LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {563LU}}, /* .binaryEncodingId */
sizeof(UA_RegisterNodesResponse), /* .memSize */
- UA_TYPES_REGISTERNODESRESPONSE, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
2, /* .membersSize */
- 563, /* .binaryEncodingId */
- RegisterNodesResponse_members /* .members */
+ RegisterNodesResponse_members /* .members */
},
/* UnregisterNodesRequest */
{
UA_TYPENAME("UnregisterNodesRequest") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {564}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {564LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {566LU}}, /* .binaryEncodingId */
sizeof(UA_UnregisterNodesRequest), /* .memSize */
- UA_TYPES_UNREGISTERNODESREQUEST, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
2, /* .membersSize */
- 566, /* .binaryEncodingId */
- UnregisterNodesRequest_members /* .members */
+ UnregisterNodesRequest_members /* .members */
},
/* UnregisterNodesResponse */
{
UA_TYPENAME("UnregisterNodesResponse") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {567}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {567LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {569LU}}, /* .binaryEncodingId */
sizeof(UA_UnregisterNodesResponse), /* .memSize */
- UA_TYPES_UNREGISTERNODESRESPONSE, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
1, /* .membersSize */
- 569, /* .binaryEncodingId */
- UnregisterNodesResponse_members /* .members */
+ UnregisterNodesResponse_members /* .members */
},
/* FilterOperator */
{
UA_TYPENAME("FilterOperator") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {576}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {576LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
sizeof(UA_FilterOperator), /* .memSize */
- UA_TYPES_INT32, /* .typeIndex */
UA_DATATYPEKIND_ENUM, /* .typeKind */
true, /* .pointerFree */
UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
0, /* .membersSize */
- 0, /* .binaryEncodingId */
- FilterOperator_members /* .members */
+ FilterOperator_members /* .members */
},
/* ContentFilterElement */
{
UA_TYPENAME("ContentFilterElement") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {583}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {583LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {585LU}}, /* .binaryEncodingId */
sizeof(UA_ContentFilterElement), /* .memSize */
- UA_TYPES_CONTENTFILTERELEMENT, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
2, /* .membersSize */
- 585, /* .binaryEncodingId */
- ContentFilterElement_members /* .members */
+ ContentFilterElement_members /* .members */
},
/* ContentFilter */
{
UA_TYPENAME("ContentFilter") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {586}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {586LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {588LU}}, /* .binaryEncodingId */
sizeof(UA_ContentFilter), /* .memSize */
- UA_TYPES_CONTENTFILTER, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
1, /* .membersSize */
- 588, /* .binaryEncodingId */
- ContentFilter_members /* .members */
-},
-/* FilterOperand */
-{
- UA_TYPENAME("FilterOperand") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {589}}, /* .typeId */
- sizeof(UA_FilterOperand), /* .memSize */
- UA_TYPES_FILTEROPERAND, /* .typeIndex */
- UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
- true, /* .pointerFree */
- false, /* .overlayable */
- 0, /* .membersSize */
- 591, /* .binaryEncodingId */
- FilterOperand_members /* .members */
+ ContentFilter_members /* .members */
},
/* ElementOperand */
{
UA_TYPENAME("ElementOperand") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {592}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {592LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {594LU}}, /* .binaryEncodingId */
sizeof(UA_ElementOperand), /* .memSize */
- UA_TYPES_ELEMENTOPERAND, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
true, /* .pointerFree */
false, /* .overlayable */
1, /* .membersSize */
- 594, /* .binaryEncodingId */
- ElementOperand_members /* .members */
+ ElementOperand_members /* .members */
},
/* LiteralOperand */
{
UA_TYPENAME("LiteralOperand") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {595}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {595LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {597LU}}, /* .binaryEncodingId */
sizeof(UA_LiteralOperand), /* .memSize */
- UA_TYPES_LITERALOPERAND, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
1, /* .membersSize */
- 597, /* .binaryEncodingId */
- LiteralOperand_members /* .members */
+ LiteralOperand_members /* .members */
},
/* AttributeOperand */
{
UA_TYPENAME("AttributeOperand") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {598}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {598LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {600LU}}, /* .binaryEncodingId */
sizeof(UA_AttributeOperand), /* .memSize */
- UA_TYPES_ATTRIBUTEOPERAND, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
5, /* .membersSize */
- 600, /* .binaryEncodingId */
- AttributeOperand_members /* .members */
+ AttributeOperand_members /* .members */
},
/* SimpleAttributeOperand */
{
UA_TYPENAME("SimpleAttributeOperand") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {601}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {601LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {603LU}}, /* .binaryEncodingId */
sizeof(UA_SimpleAttributeOperand), /* .memSize */
- UA_TYPES_SIMPLEATTRIBUTEOPERAND, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
4, /* .membersSize */
- 603, /* .binaryEncodingId */
- SimpleAttributeOperand_members /* .members */
+ SimpleAttributeOperand_members /* .members */
},
/* ContentFilterElementResult */
{
UA_TYPENAME("ContentFilterElementResult") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {604}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {604LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {606LU}}, /* .binaryEncodingId */
sizeof(UA_ContentFilterElementResult), /* .memSize */
- UA_TYPES_CONTENTFILTERELEMENTRESULT, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
3, /* .membersSize */
- 606, /* .binaryEncodingId */
- ContentFilterElementResult_members /* .members */
+ ContentFilterElementResult_members /* .members */
},
/* ContentFilterResult */
{
UA_TYPENAME("ContentFilterResult") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {607}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {607LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {609LU}}, /* .binaryEncodingId */
sizeof(UA_ContentFilterResult), /* .memSize */
- UA_TYPES_CONTENTFILTERRESULT, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
2, /* .membersSize */
- 609, /* .binaryEncodingId */
- ContentFilterResult_members /* .members */
+ ContentFilterResult_members /* .members */
},
/* TimestampsToReturn */
{
UA_TYPENAME("TimestampsToReturn") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {625}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {625LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
sizeof(UA_TimestampsToReturn), /* .memSize */
- UA_TYPES_INT32, /* .typeIndex */
UA_DATATYPEKIND_ENUM, /* .typeKind */
true, /* .pointerFree */
UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
0, /* .membersSize */
- 0, /* .binaryEncodingId */
- TimestampsToReturn_members /* .members */
+ TimestampsToReturn_members /* .members */
},
/* ReadValueId */
{
UA_TYPENAME("ReadValueId") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {626}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {626LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {628LU}}, /* .binaryEncodingId */
sizeof(UA_ReadValueId), /* .memSize */
- UA_TYPES_READVALUEID, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
4, /* .membersSize */
- 628, /* .binaryEncodingId */
- ReadValueId_members /* .members */
+ ReadValueId_members /* .members */
},
/* ReadRequest */
{
UA_TYPENAME("ReadRequest") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {629}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {629LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {631LU}}, /* .binaryEncodingId */
sizeof(UA_ReadRequest), /* .memSize */
- UA_TYPES_READREQUEST, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
4, /* .membersSize */
- 631, /* .binaryEncodingId */
- ReadRequest_members /* .members */
+ ReadRequest_members /* .members */
},
/* ReadResponse */
{
UA_TYPENAME("ReadResponse") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {632}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {632LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {634LU}}, /* .binaryEncodingId */
sizeof(UA_ReadResponse), /* .memSize */
- UA_TYPES_READRESPONSE, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
3, /* .membersSize */
- 634, /* .binaryEncodingId */
- ReadResponse_members /* .members */
+ ReadResponse_members /* .members */
},
/* HistoryReadValueId */
{
UA_TYPENAME("HistoryReadValueId") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {635}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {635LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {637LU}}, /* .binaryEncodingId */
sizeof(UA_HistoryReadValueId), /* .memSize */
- UA_TYPES_HISTORYREADVALUEID, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
4, /* .membersSize */
- 637, /* .binaryEncodingId */
- HistoryReadValueId_members /* .members */
+ HistoryReadValueId_members /* .members */
},
/* HistoryReadResult */
{
UA_TYPENAME("HistoryReadResult") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {638}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {638LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {640LU}}, /* .binaryEncodingId */
sizeof(UA_HistoryReadResult), /* .memSize */
- UA_TYPES_HISTORYREADRESULT, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
3, /* .membersSize */
- 640, /* .binaryEncodingId */
- HistoryReadResult_members /* .members */
+ HistoryReadResult_members /* .members */
},
/* ReadRawModifiedDetails */
{
UA_TYPENAME("ReadRawModifiedDetails") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {647}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {647LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {649LU}}, /* .binaryEncodingId */
sizeof(UA_ReadRawModifiedDetails), /* .memSize */
- UA_TYPES_READRAWMODIFIEDDETAILS, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
true, /* .pointerFree */
false, /* .overlayable */
5, /* .membersSize */
- 649, /* .binaryEncodingId */
- ReadRawModifiedDetails_members /* .members */
+ ReadRawModifiedDetails_members /* .members */
},
/* ReadAtTimeDetails */
{
UA_TYPENAME("ReadAtTimeDetails") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {653}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {653LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {655LU}}, /* .binaryEncodingId */
sizeof(UA_ReadAtTimeDetails), /* .memSize */
- UA_TYPES_READATTIMEDETAILS, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
2, /* .membersSize */
- 655, /* .binaryEncodingId */
- ReadAtTimeDetails_members /* .members */
+ ReadAtTimeDetails_members /* .members */
},
/* HistoryData */
{
UA_TYPENAME("HistoryData") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {656}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {656LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {658LU}}, /* .binaryEncodingId */
sizeof(UA_HistoryData), /* .memSize */
- UA_TYPES_HISTORYDATA, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
1, /* .membersSize */
- 658, /* .binaryEncodingId */
- HistoryData_members /* .members */
+ HistoryData_members /* .members */
},
/* HistoryReadRequest */
{
UA_TYPENAME("HistoryReadRequest") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {662}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {662LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {664LU}}, /* .binaryEncodingId */
sizeof(UA_HistoryReadRequest), /* .memSize */
- UA_TYPES_HISTORYREADREQUEST, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
5, /* .membersSize */
- 664, /* .binaryEncodingId */
- HistoryReadRequest_members /* .members */
+ HistoryReadRequest_members /* .members */
},
/* HistoryReadResponse */
{
UA_TYPENAME("HistoryReadResponse") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {665}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {665LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {667LU}}, /* .binaryEncodingId */
sizeof(UA_HistoryReadResponse), /* .memSize */
- UA_TYPES_HISTORYREADRESPONSE, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
3, /* .membersSize */
- 667, /* .binaryEncodingId */
- HistoryReadResponse_members /* .members */
+ HistoryReadResponse_members /* .members */
},
/* WriteValue */
{
UA_TYPENAME("WriteValue") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {668}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {668LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {670LU}}, /* .binaryEncodingId */
sizeof(UA_WriteValue), /* .memSize */
- UA_TYPES_WRITEVALUE, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
4, /* .membersSize */
- 670, /* .binaryEncodingId */
- WriteValue_members /* .members */
+ WriteValue_members /* .members */
},
/* WriteRequest */
{
UA_TYPENAME("WriteRequest") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {671}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {671LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {673LU}}, /* .binaryEncodingId */
sizeof(UA_WriteRequest), /* .memSize */
- UA_TYPES_WRITEREQUEST, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
2, /* .membersSize */
- 673, /* .binaryEncodingId */
- WriteRequest_members /* .members */
+ WriteRequest_members /* .members */
},
/* WriteResponse */
{
UA_TYPENAME("WriteResponse") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {674}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {674LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {676LU}}, /* .binaryEncodingId */
sizeof(UA_WriteResponse), /* .memSize */
- UA_TYPES_WRITERESPONSE, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
3, /* .membersSize */
- 676, /* .binaryEncodingId */
- WriteResponse_members /* .members */
+ WriteResponse_members /* .members */
},
/* HistoryUpdateType */
{
UA_TYPENAME("HistoryUpdateType") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {11234}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {11234LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
sizeof(UA_HistoryUpdateType), /* .memSize */
- UA_TYPES_INT32, /* .typeIndex */
UA_DATATYPEKIND_ENUM, /* .typeKind */
true, /* .pointerFree */
UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
0, /* .membersSize */
- 0, /* .binaryEncodingId */
- HistoryUpdateType_members /* .members */
+ HistoryUpdateType_members /* .members */
},
/* PerformUpdateType */
{
UA_TYPENAME("PerformUpdateType") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {11293}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {11293LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
sizeof(UA_PerformUpdateType), /* .memSize */
- UA_TYPES_INT32, /* .typeIndex */
UA_DATATYPEKIND_ENUM, /* .typeKind */
true, /* .pointerFree */
UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
0, /* .membersSize */
- 0, /* .binaryEncodingId */
- PerformUpdateType_members /* .members */
+ PerformUpdateType_members /* .members */
},
/* UpdateDataDetails */
{
UA_TYPENAME("UpdateDataDetails") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {680}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {680LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {682LU}}, /* .binaryEncodingId */
sizeof(UA_UpdateDataDetails), /* .memSize */
- UA_TYPES_UPDATEDATADETAILS, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
3, /* .membersSize */
- 682, /* .binaryEncodingId */
- UpdateDataDetails_members /* .members */
+ UpdateDataDetails_members /* .members */
},
/* DeleteRawModifiedDetails */
{
UA_TYPENAME("DeleteRawModifiedDetails") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {686}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {686LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {688LU}}, /* .binaryEncodingId */
sizeof(UA_DeleteRawModifiedDetails), /* .memSize */
- UA_TYPES_DELETERAWMODIFIEDDETAILS, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
4, /* .membersSize */
- 688, /* .binaryEncodingId */
- DeleteRawModifiedDetails_members /* .members */
+ DeleteRawModifiedDetails_members /* .members */
},
/* HistoryUpdateResult */
{
UA_TYPENAME("HistoryUpdateResult") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {695}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {695LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {697LU}}, /* .binaryEncodingId */
sizeof(UA_HistoryUpdateResult), /* .memSize */
- UA_TYPES_HISTORYUPDATERESULT, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
3, /* .membersSize */
- 697, /* .binaryEncodingId */
- HistoryUpdateResult_members /* .members */
+ HistoryUpdateResult_members /* .members */
},
/* HistoryUpdateRequest */
{
UA_TYPENAME("HistoryUpdateRequest") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {698}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {698LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {700LU}}, /* .binaryEncodingId */
sizeof(UA_HistoryUpdateRequest), /* .memSize */
- UA_TYPES_HISTORYUPDATEREQUEST, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
2, /* .membersSize */
- 700, /* .binaryEncodingId */
- HistoryUpdateRequest_members /* .members */
+ HistoryUpdateRequest_members /* .members */
},
/* HistoryUpdateResponse */
{
UA_TYPENAME("HistoryUpdateResponse") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {701}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {701LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {703LU}}, /* .binaryEncodingId */
sizeof(UA_HistoryUpdateResponse), /* .memSize */
- UA_TYPES_HISTORYUPDATERESPONSE, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
3, /* .membersSize */
- 703, /* .binaryEncodingId */
- HistoryUpdateResponse_members /* .members */
+ HistoryUpdateResponse_members /* .members */
},
/* CallMethodRequest */
{
UA_TYPENAME("CallMethodRequest") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {704}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {704LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {706LU}}, /* .binaryEncodingId */
sizeof(UA_CallMethodRequest), /* .memSize */
- UA_TYPES_CALLMETHODREQUEST, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
3, /* .membersSize */
- 706, /* .binaryEncodingId */
- CallMethodRequest_members /* .members */
+ CallMethodRequest_members /* .members */
},
/* CallMethodResult */
{
UA_TYPENAME("CallMethodResult") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {707}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {707LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {709LU}}, /* .binaryEncodingId */
sizeof(UA_CallMethodResult), /* .memSize */
- UA_TYPES_CALLMETHODRESULT, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
4, /* .membersSize */
- 709, /* .binaryEncodingId */
- CallMethodResult_members /* .members */
+ CallMethodResult_members /* .members */
},
/* CallRequest */
{
UA_TYPENAME("CallRequest") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {710}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {710LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {712LU}}, /* .binaryEncodingId */
sizeof(UA_CallRequest), /* .memSize */
- UA_TYPES_CALLREQUEST, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
2, /* .membersSize */
- 712, /* .binaryEncodingId */
- CallRequest_members /* .members */
+ CallRequest_members /* .members */
},
/* CallResponse */
{
UA_TYPENAME("CallResponse") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {713}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {713LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {715LU}}, /* .binaryEncodingId */
sizeof(UA_CallResponse), /* .memSize */
- UA_TYPES_CALLRESPONSE, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
3, /* .membersSize */
- 715, /* .binaryEncodingId */
- CallResponse_members /* .members */
+ CallResponse_members /* .members */
},
/* MonitoringMode */
{
UA_TYPENAME("MonitoringMode") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {716}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {716LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
sizeof(UA_MonitoringMode), /* .memSize */
- UA_TYPES_INT32, /* .typeIndex */
UA_DATATYPEKIND_ENUM, /* .typeKind */
true, /* .pointerFree */
UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
0, /* .membersSize */
- 0, /* .binaryEncodingId */
- MonitoringMode_members /* .members */
+ MonitoringMode_members /* .members */
},
/* DataChangeTrigger */
{
UA_TYPENAME("DataChangeTrigger") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {717}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {717LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
sizeof(UA_DataChangeTrigger), /* .memSize */
- UA_TYPES_INT32, /* .typeIndex */
UA_DATATYPEKIND_ENUM, /* .typeKind */
true, /* .pointerFree */
UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
0, /* .membersSize */
- 0, /* .binaryEncodingId */
- DataChangeTrigger_members /* .members */
+ DataChangeTrigger_members /* .members */
},
/* DeadbandType */
{
UA_TYPENAME("DeadbandType") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {718}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {718LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
sizeof(UA_DeadbandType), /* .memSize */
- UA_TYPES_INT32, /* .typeIndex */
UA_DATATYPEKIND_ENUM, /* .typeKind */
true, /* .pointerFree */
UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
0, /* .membersSize */
- 0, /* .binaryEncodingId */
- DeadbandType_members /* .members */
+ DeadbandType_members /* .members */
},
/* DataChangeFilter */
{
UA_TYPENAME("DataChangeFilter") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {722}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {722LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {724LU}}, /* .binaryEncodingId */
sizeof(UA_DataChangeFilter), /* .memSize */
- UA_TYPES_DATACHANGEFILTER, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
true, /* .pointerFree */
false, /* .overlayable */
3, /* .membersSize */
- 724, /* .binaryEncodingId */
- DataChangeFilter_members /* .members */
+ DataChangeFilter_members /* .members */
},
/* EventFilter */
{
UA_TYPENAME("EventFilter") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {725}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {725LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {727LU}}, /* .binaryEncodingId */
sizeof(UA_EventFilter), /* .memSize */
- UA_TYPES_EVENTFILTER, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
2, /* .membersSize */
- 727, /* .binaryEncodingId */
- EventFilter_members /* .members */
+ EventFilter_members /* .members */
},
/* AggregateConfiguration */
{
UA_TYPENAME("AggregateConfiguration") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {948}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {948LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {950LU}}, /* .binaryEncodingId */
sizeof(UA_AggregateConfiguration), /* .memSize */
- UA_TYPES_AGGREGATECONFIGURATION, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
true, /* .pointerFree */
false, /* .overlayable */
5, /* .membersSize */
- 950, /* .binaryEncodingId */
- AggregateConfiguration_members /* .members */
+ AggregateConfiguration_members /* .members */
},
/* AggregateFilter */
{
UA_TYPENAME("AggregateFilter") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {728}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {728LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {730LU}}, /* .binaryEncodingId */
sizeof(UA_AggregateFilter), /* .memSize */
- UA_TYPES_AGGREGATEFILTER, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
4, /* .membersSize */
- 730, /* .binaryEncodingId */
- AggregateFilter_members /* .members */
+ AggregateFilter_members /* .members */
},
/* EventFilterResult */
{
UA_TYPENAME("EventFilterResult") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {734}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {734LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {736LU}}, /* .binaryEncodingId */
sizeof(UA_EventFilterResult), /* .memSize */
- UA_TYPES_EVENTFILTERRESULT, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
3, /* .membersSize */
- 736, /* .binaryEncodingId */
- EventFilterResult_members /* .members */
+ EventFilterResult_members /* .members */
},
/* MonitoringParameters */
{
UA_TYPENAME("MonitoringParameters") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {740}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {740LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {742LU}}, /* .binaryEncodingId */
sizeof(UA_MonitoringParameters), /* .memSize */
- UA_TYPES_MONITORINGPARAMETERS, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
5, /* .membersSize */
- 742, /* .binaryEncodingId */
- MonitoringParameters_members /* .members */
+ MonitoringParameters_members /* .members */
},
/* MonitoredItemCreateRequest */
{
UA_TYPENAME("MonitoredItemCreateRequest") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {743}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {743LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {745LU}}, /* .binaryEncodingId */
sizeof(UA_MonitoredItemCreateRequest), /* .memSize */
- UA_TYPES_MONITOREDITEMCREATEREQUEST, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
3, /* .membersSize */
- 745, /* .binaryEncodingId */
- MonitoredItemCreateRequest_members /* .members */
+ MonitoredItemCreateRequest_members /* .members */
},
/* MonitoredItemCreateResult */
{
UA_TYPENAME("MonitoredItemCreateResult") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {746}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {746LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {748LU}}, /* .binaryEncodingId */
sizeof(UA_MonitoredItemCreateResult), /* .memSize */
- UA_TYPES_MONITOREDITEMCREATERESULT, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
5, /* .membersSize */
- 748, /* .binaryEncodingId */
- MonitoredItemCreateResult_members /* .members */
+ MonitoredItemCreateResult_members /* .members */
},
/* CreateMonitoredItemsRequest */
{
UA_TYPENAME("CreateMonitoredItemsRequest") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {749}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {749LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {751LU}}, /* .binaryEncodingId */
sizeof(UA_CreateMonitoredItemsRequest), /* .memSize */
- UA_TYPES_CREATEMONITOREDITEMSREQUEST, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
4, /* .membersSize */
- 751, /* .binaryEncodingId */
- CreateMonitoredItemsRequest_members /* .members */
+ CreateMonitoredItemsRequest_members /* .members */
},
/* CreateMonitoredItemsResponse */
{
UA_TYPENAME("CreateMonitoredItemsResponse") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {752}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {752LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {754LU}}, /* .binaryEncodingId */
sizeof(UA_CreateMonitoredItemsResponse), /* .memSize */
- UA_TYPES_CREATEMONITOREDITEMSRESPONSE, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
3, /* .membersSize */
- 754, /* .binaryEncodingId */
- CreateMonitoredItemsResponse_members /* .members */
+ CreateMonitoredItemsResponse_members /* .members */
},
/* MonitoredItemModifyRequest */
{
UA_TYPENAME("MonitoredItemModifyRequest") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {755}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {755LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {757LU}}, /* .binaryEncodingId */
sizeof(UA_MonitoredItemModifyRequest), /* .memSize */
- UA_TYPES_MONITOREDITEMMODIFYREQUEST, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
2, /* .membersSize */
- 757, /* .binaryEncodingId */
- MonitoredItemModifyRequest_members /* .members */
+ MonitoredItemModifyRequest_members /* .members */
},
/* MonitoredItemModifyResult */
{
UA_TYPENAME("MonitoredItemModifyResult") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {758}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {758LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {760LU}}, /* .binaryEncodingId */
sizeof(UA_MonitoredItemModifyResult), /* .memSize */
- UA_TYPES_MONITOREDITEMMODIFYRESULT, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
4, /* .membersSize */
- 760, /* .binaryEncodingId */
- MonitoredItemModifyResult_members /* .members */
+ MonitoredItemModifyResult_members /* .members */
},
/* ModifyMonitoredItemsRequest */
{
UA_TYPENAME("ModifyMonitoredItemsRequest") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {761}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {761LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {763LU}}, /* .binaryEncodingId */
sizeof(UA_ModifyMonitoredItemsRequest), /* .memSize */
- UA_TYPES_MODIFYMONITOREDITEMSREQUEST, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
4, /* .membersSize */
- 763, /* .binaryEncodingId */
- ModifyMonitoredItemsRequest_members /* .members */
+ ModifyMonitoredItemsRequest_members /* .members */
},
/* ModifyMonitoredItemsResponse */
{
UA_TYPENAME("ModifyMonitoredItemsResponse") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {764}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {764LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {766LU}}, /* .binaryEncodingId */
sizeof(UA_ModifyMonitoredItemsResponse), /* .memSize */
- UA_TYPES_MODIFYMONITOREDITEMSRESPONSE, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
3, /* .membersSize */
- 766, /* .binaryEncodingId */
- ModifyMonitoredItemsResponse_members /* .members */
+ ModifyMonitoredItemsResponse_members /* .members */
},
/* SetMonitoringModeRequest */
{
UA_TYPENAME("SetMonitoringModeRequest") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {767}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {767LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {769LU}}, /* .binaryEncodingId */
sizeof(UA_SetMonitoringModeRequest), /* .memSize */
- UA_TYPES_SETMONITORINGMODEREQUEST, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
4, /* .membersSize */
- 769, /* .binaryEncodingId */
- SetMonitoringModeRequest_members /* .members */
+ SetMonitoringModeRequest_members /* .members */
},
/* SetMonitoringModeResponse */
{
UA_TYPENAME("SetMonitoringModeResponse") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {770}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {770LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {772LU}}, /* .binaryEncodingId */
sizeof(UA_SetMonitoringModeResponse), /* .memSize */
- UA_TYPES_SETMONITORINGMODERESPONSE, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
3, /* .membersSize */
- 772, /* .binaryEncodingId */
- SetMonitoringModeResponse_members /* .members */
+ SetMonitoringModeResponse_members /* .members */
},
/* SetTriggeringRequest */
{
UA_TYPENAME("SetTriggeringRequest") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {773}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {773LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {775LU}}, /* .binaryEncodingId */
sizeof(UA_SetTriggeringRequest), /* .memSize */
- UA_TYPES_SETTRIGGERINGREQUEST, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
5, /* .membersSize */
- 775, /* .binaryEncodingId */
- SetTriggeringRequest_members /* .members */
+ SetTriggeringRequest_members /* .members */
},
/* SetTriggeringResponse */
{
UA_TYPENAME("SetTriggeringResponse") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {776}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {776LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {778LU}}, /* .binaryEncodingId */
sizeof(UA_SetTriggeringResponse), /* .memSize */
- UA_TYPES_SETTRIGGERINGRESPONSE, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
5, /* .membersSize */
- 778, /* .binaryEncodingId */
- SetTriggeringResponse_members /* .members */
+ SetTriggeringResponse_members /* .members */
},
/* DeleteMonitoredItemsRequest */
{
UA_TYPENAME("DeleteMonitoredItemsRequest") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {779}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {779LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {781LU}}, /* .binaryEncodingId */
sizeof(UA_DeleteMonitoredItemsRequest), /* .memSize */
- UA_TYPES_DELETEMONITOREDITEMSREQUEST, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
3, /* .membersSize */
- 781, /* .binaryEncodingId */
- DeleteMonitoredItemsRequest_members /* .members */
+ DeleteMonitoredItemsRequest_members /* .members */
},
/* DeleteMonitoredItemsResponse */
{
UA_TYPENAME("DeleteMonitoredItemsResponse") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {782}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {782LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {784LU}}, /* .binaryEncodingId */
sizeof(UA_DeleteMonitoredItemsResponse), /* .memSize */
- UA_TYPES_DELETEMONITOREDITEMSRESPONSE, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
3, /* .membersSize */
- 784, /* .binaryEncodingId */
- DeleteMonitoredItemsResponse_members /* .members */
+ DeleteMonitoredItemsResponse_members /* .members */
},
/* CreateSubscriptionRequest */
{
UA_TYPENAME("CreateSubscriptionRequest") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {785}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {785LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {787LU}}, /* .binaryEncodingId */
sizeof(UA_CreateSubscriptionRequest), /* .memSize */
- UA_TYPES_CREATESUBSCRIPTIONREQUEST, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
7, /* .membersSize */
- 787, /* .binaryEncodingId */
- CreateSubscriptionRequest_members /* .members */
+ CreateSubscriptionRequest_members /* .members */
},
/* CreateSubscriptionResponse */
{
UA_TYPENAME("CreateSubscriptionResponse") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {788}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {788LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {790LU}}, /* .binaryEncodingId */
sizeof(UA_CreateSubscriptionResponse), /* .memSize */
- UA_TYPES_CREATESUBSCRIPTIONRESPONSE, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
5, /* .membersSize */
- 790, /* .binaryEncodingId */
- CreateSubscriptionResponse_members /* .members */
+ CreateSubscriptionResponse_members /* .members */
},
/* ModifySubscriptionRequest */
{
UA_TYPENAME("ModifySubscriptionRequest") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {791}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {791LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {793LU}}, /* .binaryEncodingId */
sizeof(UA_ModifySubscriptionRequest), /* .memSize */
- UA_TYPES_MODIFYSUBSCRIPTIONREQUEST, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
7, /* .membersSize */
- 793, /* .binaryEncodingId */
- ModifySubscriptionRequest_members /* .members */
+ ModifySubscriptionRequest_members /* .members */
},
/* ModifySubscriptionResponse */
{
UA_TYPENAME("ModifySubscriptionResponse") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {794}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {794LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {796LU}}, /* .binaryEncodingId */
sizeof(UA_ModifySubscriptionResponse), /* .memSize */
- UA_TYPES_MODIFYSUBSCRIPTIONRESPONSE, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
4, /* .membersSize */
- 796, /* .binaryEncodingId */
- ModifySubscriptionResponse_members /* .members */
+ ModifySubscriptionResponse_members /* .members */
},
/* SetPublishingModeRequest */
{
UA_TYPENAME("SetPublishingModeRequest") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {797}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {797LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {799LU}}, /* .binaryEncodingId */
sizeof(UA_SetPublishingModeRequest), /* .memSize */
- UA_TYPES_SETPUBLISHINGMODEREQUEST, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
3, /* .membersSize */
- 799, /* .binaryEncodingId */
- SetPublishingModeRequest_members /* .members */
+ SetPublishingModeRequest_members /* .members */
},
/* SetPublishingModeResponse */
{
UA_TYPENAME("SetPublishingModeResponse") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {800}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {800LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {802LU}}, /* .binaryEncodingId */
sizeof(UA_SetPublishingModeResponse), /* .memSize */
- UA_TYPES_SETPUBLISHINGMODERESPONSE, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
3, /* .membersSize */
- 802, /* .binaryEncodingId */
- SetPublishingModeResponse_members /* .members */
+ SetPublishingModeResponse_members /* .members */
},
/* NotificationMessage */
{
UA_TYPENAME("NotificationMessage") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {803}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {803LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {805LU}}, /* .binaryEncodingId */
sizeof(UA_NotificationMessage), /* .memSize */
- UA_TYPES_NOTIFICATIONMESSAGE, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
3, /* .membersSize */
- 805, /* .binaryEncodingId */
- NotificationMessage_members /* .members */
+ NotificationMessage_members /* .members */
},
/* MonitoredItemNotification */
{
UA_TYPENAME("MonitoredItemNotification") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {806}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {806LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {808LU}}, /* .binaryEncodingId */
sizeof(UA_MonitoredItemNotification), /* .memSize */
- UA_TYPES_MONITOREDITEMNOTIFICATION, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
2, /* .membersSize */
- 808, /* .binaryEncodingId */
- MonitoredItemNotification_members /* .members */
+ MonitoredItemNotification_members /* .members */
},
/* EventFieldList */
{
UA_TYPENAME("EventFieldList") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {917}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {917LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {919LU}}, /* .binaryEncodingId */
sizeof(UA_EventFieldList), /* .memSize */
- UA_TYPES_EVENTFIELDLIST, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
2, /* .membersSize */
- 919, /* .binaryEncodingId */
- EventFieldList_members /* .members */
+ EventFieldList_members /* .members */
},
/* HistoryEventFieldList */
{
UA_TYPENAME("HistoryEventFieldList") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {920}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {920LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {922LU}}, /* .binaryEncodingId */
sizeof(UA_HistoryEventFieldList), /* .memSize */
- UA_TYPES_HISTORYEVENTFIELDLIST, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
1, /* .membersSize */
- 922, /* .binaryEncodingId */
- HistoryEventFieldList_members /* .members */
+ HistoryEventFieldList_members /* .members */
},
/* StatusChangeNotification */
{
UA_TYPENAME("StatusChangeNotification") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {818}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {818LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {820LU}}, /* .binaryEncodingId */
sizeof(UA_StatusChangeNotification), /* .memSize */
- UA_TYPES_STATUSCHANGENOTIFICATION, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
2, /* .membersSize */
- 820, /* .binaryEncodingId */
- StatusChangeNotification_members /* .members */
+ StatusChangeNotification_members /* .members */
},
/* SubscriptionAcknowledgement */
{
UA_TYPENAME("SubscriptionAcknowledgement") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {821}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {821LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {823LU}}, /* .binaryEncodingId */
sizeof(UA_SubscriptionAcknowledgement), /* .memSize */
- UA_TYPES_SUBSCRIPTIONACKNOWLEDGEMENT, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
true, /* .pointerFree */
false, /* .overlayable */
2, /* .membersSize */
- 823, /* .binaryEncodingId */
- SubscriptionAcknowledgement_members /* .members */
+ SubscriptionAcknowledgement_members /* .members */
},
/* PublishRequest */
{
UA_TYPENAME("PublishRequest") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {824}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {824LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {826LU}}, /* .binaryEncodingId */
sizeof(UA_PublishRequest), /* .memSize */
- UA_TYPES_PUBLISHREQUEST, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
2, /* .membersSize */
- 826, /* .binaryEncodingId */
- PublishRequest_members /* .members */
+ PublishRequest_members /* .members */
},
/* PublishResponse */
{
UA_TYPENAME("PublishResponse") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {827}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {827LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {829LU}}, /* .binaryEncodingId */
sizeof(UA_PublishResponse), /* .memSize */
- UA_TYPES_PUBLISHRESPONSE, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
7, /* .membersSize */
- 829, /* .binaryEncodingId */
- PublishResponse_members /* .members */
+ PublishResponse_members /* .members */
},
/* RepublishRequest */
{
UA_TYPENAME("RepublishRequest") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {830}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {830LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {832LU}}, /* .binaryEncodingId */
sizeof(UA_RepublishRequest), /* .memSize */
- UA_TYPES_REPUBLISHREQUEST, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
3, /* .membersSize */
- 832, /* .binaryEncodingId */
- RepublishRequest_members /* .members */
+ RepublishRequest_members /* .members */
},
/* RepublishResponse */
{
UA_TYPENAME("RepublishResponse") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {833}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {833LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {835LU}}, /* .binaryEncodingId */
sizeof(UA_RepublishResponse), /* .memSize */
- UA_TYPES_REPUBLISHRESPONSE, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
2, /* .membersSize */
- 835, /* .binaryEncodingId */
- RepublishResponse_members /* .members */
+ RepublishResponse_members /* .members */
+},
+/* TransferResult */
+{
+ UA_TYPENAME("TransferResult") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {836LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {838LU}}, /* .binaryEncodingId */
+ sizeof(UA_TransferResult), /* .memSize */
+ UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 2, /* .membersSize */
+ TransferResult_members /* .members */
+},
+/* TransferSubscriptionsRequest */
+{
+ UA_TYPENAME("TransferSubscriptionsRequest") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {839LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {841LU}}, /* .binaryEncodingId */
+ sizeof(UA_TransferSubscriptionsRequest), /* .memSize */
+ UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 3, /* .membersSize */
+ TransferSubscriptionsRequest_members /* .members */
+},
+/* TransferSubscriptionsResponse */
+{
+ UA_TYPENAME("TransferSubscriptionsResponse") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {842LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {844LU}}, /* .binaryEncodingId */
+ sizeof(UA_TransferSubscriptionsResponse), /* .memSize */
+ UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 3, /* .membersSize */
+ TransferSubscriptionsResponse_members /* .members */
},
/* DeleteSubscriptionsRequest */
{
UA_TYPENAME("DeleteSubscriptionsRequest") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {845}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {845LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {847LU}}, /* .binaryEncodingId */
sizeof(UA_DeleteSubscriptionsRequest), /* .memSize */
- UA_TYPES_DELETESUBSCRIPTIONSREQUEST, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
2, /* .membersSize */
- 847, /* .binaryEncodingId */
- DeleteSubscriptionsRequest_members /* .members */
+ DeleteSubscriptionsRequest_members /* .members */
},
/* DeleteSubscriptionsResponse */
{
UA_TYPENAME("DeleteSubscriptionsResponse") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {848}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {848LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {850LU}}, /* .binaryEncodingId */
sizeof(UA_DeleteSubscriptionsResponse), /* .memSize */
- UA_TYPES_DELETESUBSCRIPTIONSRESPONSE, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
3, /* .membersSize */
- 850, /* .binaryEncodingId */
- DeleteSubscriptionsResponse_members /* .members */
+ DeleteSubscriptionsResponse_members /* .members */
},
/* BuildInfo */
{
UA_TYPENAME("BuildInfo") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {338}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {338LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {340LU}}, /* .binaryEncodingId */
sizeof(UA_BuildInfo), /* .memSize */
- UA_TYPES_BUILDINFO, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
6, /* .membersSize */
- 340, /* .binaryEncodingId */
- BuildInfo_members /* .members */
+ BuildInfo_members /* .members */
},
/* RedundancySupport */
{
UA_TYPENAME("RedundancySupport") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {851}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {851LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
sizeof(UA_RedundancySupport), /* .memSize */
- UA_TYPES_INT32, /* .typeIndex */
UA_DATATYPEKIND_ENUM, /* .typeKind */
true, /* .pointerFree */
UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
0, /* .membersSize */
- 0, /* .binaryEncodingId */
- RedundancySupport_members /* .members */
+ RedundancySupport_members /* .members */
},
/* ServerState */
{
UA_TYPENAME("ServerState") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {852}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {852LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
sizeof(UA_ServerState), /* .memSize */
- UA_TYPES_INT32, /* .typeIndex */
UA_DATATYPEKIND_ENUM, /* .typeKind */
true, /* .pointerFree */
UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
0, /* .membersSize */
- 0, /* .binaryEncodingId */
- ServerState_members /* .members */
+ ServerState_members /* .members */
},
/* ServerDiagnosticsSummaryDataType */
{
UA_TYPENAME("ServerDiagnosticsSummaryDataType") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {859}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {859LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {861LU}}, /* .binaryEncodingId */
sizeof(UA_ServerDiagnosticsSummaryDataType), /* .memSize */
- UA_TYPES_SERVERDIAGNOSTICSSUMMARYDATATYPE, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
true, /* .pointerFree */
false, /* .overlayable */
12, /* .membersSize */
- 861, /* .binaryEncodingId */
- ServerDiagnosticsSummaryDataType_members /* .members */
+ ServerDiagnosticsSummaryDataType_members /* .members */
},
/* ServerStatusDataType */
{
UA_TYPENAME("ServerStatusDataType") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {862}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {862LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {864LU}}, /* .binaryEncodingId */
sizeof(UA_ServerStatusDataType), /* .memSize */
- UA_TYPES_SERVERSTATUSDATATYPE, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
6, /* .membersSize */
- 864, /* .binaryEncodingId */
- ServerStatusDataType_members /* .members */
+ ServerStatusDataType_members /* .members */
},
/* Range */
{
UA_TYPENAME("Range") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {884}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {884LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {886LU}}, /* .binaryEncodingId */
sizeof(UA_Range), /* .memSize */
- UA_TYPES_RANGE, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
true, /* .pointerFree */
false, /* .overlayable */
2, /* .membersSize */
- 886, /* .binaryEncodingId */
- Range_members /* .members */
+ Range_members /* .members */
},
/* EUInformation */
{
UA_TYPENAME("EUInformation") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {887}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {887LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {889LU}}, /* .binaryEncodingId */
sizeof(UA_EUInformation), /* .memSize */
- UA_TYPES_EUINFORMATION, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
4, /* .membersSize */
- 889, /* .binaryEncodingId */
- EUInformation_members /* .members */
+ EUInformation_members /* .members */
},
/* AxisScaleEnumeration */
{
UA_TYPENAME("AxisScaleEnumeration") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {12077}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {12077LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
sizeof(UA_AxisScaleEnumeration), /* .memSize */
- UA_TYPES_INT32, /* .typeIndex */
UA_DATATYPEKIND_ENUM, /* .typeKind */
true, /* .pointerFree */
UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
0, /* .membersSize */
- 0, /* .binaryEncodingId */
- AxisScaleEnumeration_members /* .members */
+ AxisScaleEnumeration_members /* .members */
},
/* ComplexNumberType */
{
UA_TYPENAME("ComplexNumberType") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {12171}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {12171LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {12181LU}}, /* .binaryEncodingId */
sizeof(UA_ComplexNumberType), /* .memSize */
- UA_TYPES_COMPLEXNUMBERTYPE, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
true, /* .pointerFree */
false, /* .overlayable */
2, /* .membersSize */
- 12181, /* .binaryEncodingId */
- ComplexNumberType_members /* .members */
+ ComplexNumberType_members /* .members */
},
/* DoubleComplexNumberType */
{
UA_TYPENAME("DoubleComplexNumberType") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {12172}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {12172LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {12182LU}}, /* .binaryEncodingId */
sizeof(UA_DoubleComplexNumberType), /* .memSize */
- UA_TYPES_DOUBLECOMPLEXNUMBERTYPE, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
true, /* .pointerFree */
false, /* .overlayable */
2, /* .membersSize */
- 12182, /* .binaryEncodingId */
- DoubleComplexNumberType_members /* .members */
+ DoubleComplexNumberType_members /* .members */
},
/* AxisInformation */
{
UA_TYPENAME("AxisInformation") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {12079}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {12079LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {12089LU}}, /* .binaryEncodingId */
sizeof(UA_AxisInformation), /* .memSize */
- UA_TYPES_AXISINFORMATION, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
5, /* .membersSize */
- 12089, /* .binaryEncodingId */
- AxisInformation_members /* .members */
+ AxisInformation_members /* .members */
},
/* XVType */
{
UA_TYPENAME("XVType") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {12080}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {12080LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {12090LU}}, /* .binaryEncodingId */
sizeof(UA_XVType), /* .memSize */
- UA_TYPES_XVTYPE, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
true, /* .pointerFree */
false, /* .overlayable */
2, /* .membersSize */
- 12090, /* .binaryEncodingId */
- XVType_members /* .members */
+ XVType_members /* .members */
},
/* EnumDefinition */
{
UA_TYPENAME("EnumDefinition") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {100}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {100LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {123LU}}, /* .binaryEncodingId */
sizeof(UA_EnumDefinition), /* .memSize */
- UA_TYPES_ENUMDEFINITION, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
1, /* .membersSize */
- 123, /* .binaryEncodingId */
- EnumDefinition_members /* .members */
+ EnumDefinition_members /* .members */
},
/* ReadEventDetails */
{
UA_TYPENAME("ReadEventDetails") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {644}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {644LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {646LU}}, /* .binaryEncodingId */
sizeof(UA_ReadEventDetails), /* .memSize */
- UA_TYPES_READEVENTDETAILS, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
4, /* .membersSize */
- 646, /* .binaryEncodingId */
- ReadEventDetails_members /* .members */
+ ReadEventDetails_members /* .members */
},
/* ReadProcessedDetails */
{
UA_TYPENAME("ReadProcessedDetails") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {650}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {650LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {652LU}}, /* .binaryEncodingId */
sizeof(UA_ReadProcessedDetails), /* .memSize */
- UA_TYPES_READPROCESSEDDETAILS, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
5, /* .membersSize */
- 652, /* .binaryEncodingId */
- ReadProcessedDetails_members /* .members */
+ ReadProcessedDetails_members /* .members */
},
/* ModificationInfo */
{
UA_TYPENAME("ModificationInfo") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {11216}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {11216LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {11226LU}}, /* .binaryEncodingId */
sizeof(UA_ModificationInfo), /* .memSize */
- UA_TYPES_MODIFICATIONINFO, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
3, /* .membersSize */
- 11226, /* .binaryEncodingId */
- ModificationInfo_members /* .members */
+ ModificationInfo_members /* .members */
},
/* HistoryModifiedData */
{
UA_TYPENAME("HistoryModifiedData") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {11217}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {11217LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {11227LU}}, /* .binaryEncodingId */
sizeof(UA_HistoryModifiedData), /* .memSize */
- UA_TYPES_HISTORYMODIFIEDDATA, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
2, /* .membersSize */
- 11227, /* .binaryEncodingId */
- HistoryModifiedData_members /* .members */
+ HistoryModifiedData_members /* .members */
},
/* HistoryEvent */
{
UA_TYPENAME("HistoryEvent") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {659}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {659LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {661LU}}, /* .binaryEncodingId */
sizeof(UA_HistoryEvent), /* .memSize */
- UA_TYPES_HISTORYEVENT, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
1, /* .membersSize */
- 661, /* .binaryEncodingId */
- HistoryEvent_members /* .members */
+ HistoryEvent_members /* .members */
},
/* DataChangeNotification */
{
UA_TYPENAME("DataChangeNotification") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {809}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {809LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {811LU}}, /* .binaryEncodingId */
sizeof(UA_DataChangeNotification), /* .memSize */
- UA_TYPES_DATACHANGENOTIFICATION, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
2, /* .membersSize */
- 811, /* .binaryEncodingId */
- DataChangeNotification_members /* .members */
+ DataChangeNotification_members /* .members */
},
/* EventNotificationList */
{
UA_TYPENAME("EventNotificationList") /* .typeName */
- {0, UA_NODEIDTYPE_NUMERIC, {914}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {914LU}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {916LU}}, /* .binaryEncodingId */
sizeof(UA_EventNotificationList), /* .memSize */
- UA_TYPES_EVENTNOTIFICATIONLIST, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
1, /* .membersSize */
- 916, /* .binaryEncodingId */
- EventNotificationList_members /* .members */
+ EventNotificationList_members /* .members */
},
};
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/build/src_generated/open62541/transport_generated.c" ***********************************/
+/**** amalgamated original file "/build/src_generated/open62541/transport_generated.c" ****/
-/* Generated from Opc.Ua.Types.bsd, Custom.Opc.Ua.Transport.bsd with script /home/pdie/sonstiges/qtopcua/repos/open62541/tools/generate_datatypes.py
- * on host mintaka by user pdie at 2021-06-21 11:34:37 */
+/**********************************
+ * Autogenerated -- do not modify *
+ **********************************/
/* MessageType */
@@ -18940,293 +17374,264 @@ const UA_DataType UA_TYPES[UA_TYPES_COUNT] = {
static UA_DataTypeMember TcpMessageHeader_members[2] = {
{
UA_TYPENAME("MessageTypeAndChunkType") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("MessageSize") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_TcpMessageHeader, messageSize) - offsetof(UA_TcpMessageHeader, messageTypeAndChunkType) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* TcpHelloMessage */
static UA_DataTypeMember TcpHelloMessage_members[6] = {
{
UA_TYPENAME("ProtocolVersion") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("ReceiveBufferSize") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_TcpHelloMessage, receiveBufferSize) - offsetof(UA_TcpHelloMessage, protocolVersion) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("SendBufferSize") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_TcpHelloMessage, sendBufferSize) - offsetof(UA_TcpHelloMessage, receiveBufferSize) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("MaxMessageSize") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_TcpHelloMessage, maxMessageSize) - offsetof(UA_TcpHelloMessage, sendBufferSize) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("MaxChunkCount") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_TcpHelloMessage, maxChunkCount) - offsetof(UA_TcpHelloMessage, maxMessageSize) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("EndpointUrl") /* .memberName */
- UA_TYPES_STRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STRING], /* .memberType */
offsetof(UA_TcpHelloMessage, endpointUrl) - offsetof(UA_TcpHelloMessage, maxChunkCount) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* TcpAcknowledgeMessage */
static UA_DataTypeMember TcpAcknowledgeMessage_members[5] = {
{
UA_TYPENAME("ProtocolVersion") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("ReceiveBufferSize") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_TcpAcknowledgeMessage, receiveBufferSize) - offsetof(UA_TcpAcknowledgeMessage, protocolVersion) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("SendBufferSize") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_TcpAcknowledgeMessage, sendBufferSize) - offsetof(UA_TcpAcknowledgeMessage, receiveBufferSize) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("MaxMessageSize") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_TcpAcknowledgeMessage, maxMessageSize) - offsetof(UA_TcpAcknowledgeMessage, sendBufferSize) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("MaxChunkCount") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_TcpAcknowledgeMessage, maxChunkCount) - offsetof(UA_TcpAcknowledgeMessage, maxMessageSize) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* TcpErrorMessage */
static UA_DataTypeMember TcpErrorMessage_members[2] = {
{
UA_TYPENAME("Error") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("Reason") /* .memberName */
- UA_TYPES_STRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_STRING], /* .memberType */
offsetof(UA_TcpErrorMessage, reason) - offsetof(UA_TcpErrorMessage, error) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* AsymmetricAlgorithmSecurityHeader */
static UA_DataTypeMember AsymmetricAlgorithmSecurityHeader_members[3] = {
{
UA_TYPENAME("SecurityPolicyUri") /* .memberName */
- UA_TYPES_BYTESTRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("SenderCertificate") /* .memberName */
- UA_TYPES_BYTESTRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */
offsetof(UA_AsymmetricAlgorithmSecurityHeader, senderCertificate) - offsetof(UA_AsymmetricAlgorithmSecurityHeader, securityPolicyUri) - sizeof(UA_ByteString), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("ReceiverCertificateThumbprint") /* .memberName */
- UA_TYPES_BYTESTRING, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */
offsetof(UA_AsymmetricAlgorithmSecurityHeader, receiverCertificateThumbprint) - offsetof(UA_AsymmetricAlgorithmSecurityHeader, senderCertificate) - sizeof(UA_ByteString), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
/* SequenceHeader */
static UA_DataTypeMember SequenceHeader_members[2] = {
{
UA_TYPENAME("SequenceNumber") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
0, /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},
{
UA_TYPENAME("RequestId") /* .memberName */
- UA_TYPES_UINT32, /* .memberTypeIndex */
+ &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
offsetof(UA_SequenceHeader, requestId) - offsetof(UA_SequenceHeader, sequenceNumber) - sizeof(UA_UInt32), /* .padding */
- true, /* .namespaceZero */
false, /* .isArray */
- false /* .isOptional */
+ false /* .isOptional */
},};
const UA_DataType UA_TRANSPORT[UA_TRANSPORT_COUNT] = {
/* MessageType */
{
UA_TYPENAME("MessageType") /* .typeName */
{0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
sizeof(UA_MessageType), /* .memSize */
- UA_TYPES_INT32, /* .typeIndex */
UA_DATATYPEKIND_ENUM, /* .typeKind */
true, /* .pointerFree */
UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
0, /* .membersSize */
- 0, /* .binaryEncodingId */
- MessageType_members /* .members */
+ MessageType_members /* .members */
},
/* ChunkType */
{
UA_TYPENAME("ChunkType") /* .typeName */
{0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
sizeof(UA_ChunkType), /* .memSize */
- UA_TYPES_INT32, /* .typeIndex */
UA_DATATYPEKIND_ENUM, /* .typeKind */
true, /* .pointerFree */
UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
0, /* .membersSize */
- 0, /* .binaryEncodingId */
- ChunkType_members /* .members */
+ ChunkType_members /* .members */
},
/* TcpMessageHeader */
{
UA_TYPENAME("TcpMessageHeader") /* .typeName */
{0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
sizeof(UA_TcpMessageHeader), /* .memSize */
- UA_TRANSPORT_TCPMESSAGEHEADER, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
true, /* .pointerFree */
false, /* .overlayable */
2, /* .membersSize */
- 0, /* .binaryEncodingId */
- TcpMessageHeader_members /* .members */
+ TcpMessageHeader_members /* .members */
},
/* TcpHelloMessage */
{
UA_TYPENAME("TcpHelloMessage") /* .typeName */
{0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
sizeof(UA_TcpHelloMessage), /* .memSize */
- UA_TRANSPORT_TCPHELLOMESSAGE, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
6, /* .membersSize */
- 0, /* .binaryEncodingId */
- TcpHelloMessage_members /* .members */
+ TcpHelloMessage_members /* .members */
},
/* TcpAcknowledgeMessage */
{
UA_TYPENAME("TcpAcknowledgeMessage") /* .typeName */
{0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
sizeof(UA_TcpAcknowledgeMessage), /* .memSize */
- UA_TRANSPORT_TCPACKNOWLEDGEMESSAGE, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
true, /* .pointerFree */
false, /* .overlayable */
5, /* .membersSize */
- 0, /* .binaryEncodingId */
- TcpAcknowledgeMessage_members /* .members */
+ TcpAcknowledgeMessage_members /* .members */
},
/* TcpErrorMessage */
{
UA_TYPENAME("TcpErrorMessage") /* .typeName */
{0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
sizeof(UA_TcpErrorMessage), /* .memSize */
- UA_TRANSPORT_TCPERRORMESSAGE, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
2, /* .membersSize */
- 0, /* .binaryEncodingId */
- TcpErrorMessage_members /* .members */
+ TcpErrorMessage_members /* .members */
},
/* AsymmetricAlgorithmSecurityHeader */
{
UA_TYPENAME("AsymmetricAlgorithmSecurityHeader") /* .typeName */
{0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
sizeof(UA_AsymmetricAlgorithmSecurityHeader), /* .memSize */
- UA_TRANSPORT_ASYMMETRICALGORITHMSECURITYHEADER, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable */
3, /* .membersSize */
- 0, /* .binaryEncodingId */
- AsymmetricAlgorithmSecurityHeader_members /* .members */
+ AsymmetricAlgorithmSecurityHeader_members /* .members */
},
/* SequenceHeader */
{
UA_TYPENAME("SequenceHeader") /* .typeName */
{0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .typeId */
+ {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
sizeof(UA_SequenceHeader), /* .memSize */
- UA_TRANSPORT_SEQUENCEHEADER, /* .typeIndex */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
true, /* .pointerFree */
false, /* .overlayable */
2, /* .membersSize */
- 0, /* .binaryEncodingId */
- SequenceHeader_members /* .members */
+ SequenceHeader_members /* .members */
},
};
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/build/src_generated/open62541/statuscodes.c" ***********************************/
+/**** amalgamated original file "/build/src_generated/open62541/statuscodes.c" ****/
-/**********************************************************
- * Autogenerated -- do not modify
- * Generated from /home/pdie/sonstiges/qtopcua/repos/open62541/tools/schema/StatusCode.csv with script /home/pdie/sonstiges/qtopcua/repos/open62541/tools/generate_statuscode_descriptions.py
- *********************************************************/
+/**********************************
+ * Autogenerated -- do not modify *
+ **********************************/
typedef struct {
@@ -19240,9 +17645,12 @@ const char * UA_StatusCode_name(UA_StatusCode code) {
return emptyStatusCodeName;
}
#else
-static const size_t statusCodeDescriptionsSize = 237;
-static const UA_StatusCodeName statusCodeDescriptions[237] = {
+static const size_t statusCodeDescriptionsSize = 252;
+static const UA_StatusCodeName statusCodeDescriptions[252] = {
+ {UA_STATUSCODE_GOOD, "Good"},
{UA_STATUSCODE_GOOD, "Good"},
+ {UA_STATUSCODE_UNCERTAIN, "Uncertain"},
+ {UA_STATUSCODE_BAD, "Bad"},
{UA_STATUSCODE_BADUNEXPECTEDERROR, "BadUnexpectedError"},
{UA_STATUSCODE_BADINTERNALERROR, "BadInternalError"},
{UA_STATUSCODE_BADOUTOFMEMORY, "BadOutOfMemory"},
@@ -19390,6 +17798,7 @@ static const UA_StatusCodeName statusCodeDescriptions[237] = {
{UA_STATUSCODE_BADTOOMANYPUBLISHREQUESTS, "BadTooManyPublishRequests"},
{UA_STATUSCODE_BADNOSUBSCRIPTION, "BadNoSubscription"},
{UA_STATUSCODE_BADSEQUENCENUMBERUNKNOWN, "BadSequenceNumberUnknown"},
+ {UA_STATUSCODE_GOODRETRANSMISSIONQUEUENOTSUPPORTED, "GoodRetransmissionQueueNotSupported"},
{UA_STATUSCODE_BADMESSAGENOTAVAILABLE, "BadMessageNotAvailable"},
{UA_STATUSCODE_BADINSUFFICIENTCLIENTPROFILE, "BadInsufficientClientProfile"},
{UA_STATUSCODE_BADSTATENOTACTIVE, "BadStateNotActive"},
@@ -19454,6 +17863,8 @@ static const UA_StatusCodeName statusCodeDescriptions[237] = {
{UA_STATUSCODE_GOODDATAIGNORED, "GoodDataIgnored"},
{UA_STATUSCODE_BADREQUESTNOTALLOWED, "BadRequestNotAllowed"},
{UA_STATUSCODE_BADREQUESTNOTCOMPLETE, "BadRequestNotComplete"},
+ {UA_STATUSCODE_BADTICKETREQUIRED, "BadTicketRequired"},
+ {UA_STATUSCODE_BADTICKETINVALID, "BadTicketInvalid"},
{UA_STATUSCODE_GOODEDITED, "GoodEdited"},
{UA_STATUSCODE_GOODPOSTACTIONFAILED, "GoodPostActionFailed"},
{UA_STATUSCODE_UNCERTAINDOMINANTVALUECHANGED, "UncertainDominantValueChanged"},
@@ -19461,6 +17872,15 @@ static const UA_StatusCodeName statusCodeDescriptions[237] = {
{UA_STATUSCODE_BADDOMINANTVALUECHANGED, "BadDominantValueChanged"},
{UA_STATUSCODE_UNCERTAINDEPENDENTVALUECHANGED, "UncertainDependentValueChanged"},
{UA_STATUSCODE_BADDEPENDENTVALUECHANGED, "BadDependentValueChanged"},
+ {UA_STATUSCODE_GOODEDITED_DEPENDENTVALUECHANGED, "GoodEdited_DependentValueChanged"},
+ {UA_STATUSCODE_GOODEDITED_DOMINANTVALUECHANGED, "GoodEdited_DominantValueChanged"},
+ {UA_STATUSCODE_GOODEDITED_DOMINANTVALUECHANGED_DEPENDENTVALUECHANGED, "GoodEdited_DominantValueChanged_DependentValueChanged"},
+ {UA_STATUSCODE_BADEDITED_OUTOFRANGE, "BadEdited_OutOfRange"},
+ {UA_STATUSCODE_BADINITIALVALUE_OUTOFRANGE, "BadInitialValue_OutOfRange"},
+ {UA_STATUSCODE_BADOUTOFRANGE_DOMINANTVALUECHANGED, "BadOutOfRange_DominantValueChanged"},
+ {UA_STATUSCODE_BADEDITED_OUTOFRANGE_DOMINANTVALUECHANGED, "BadEdited_OutOfRange_DominantValueChanged"},
+ {UA_STATUSCODE_BADOUTOFRANGE_DOMINANTVALUECHANGED_DEPENDENTVALUECHANGED, "BadOutOfRange_DominantValueChanged_DependentValueChanged"},
+ {UA_STATUSCODE_BADEDITED_OUTOFRANGE_DOMINANTVALUECHANGED_DEPENDENTVALUECHANGED, "BadEdited_OutOfRange_DominantValueChanged_DependentValueChanged"},
{UA_STATUSCODE_GOODCOMMUNICATIONEVENT, "GoodCommunicationEvent"},
{UA_STATUSCODE_GOODSHUTDOWNEVENT, "GoodShutdownEvent"},
{UA_STATUSCODE_GOODCALLAGAIN, "GoodCallAgain"},
@@ -19483,7 +17903,7 @@ static const UA_StatusCodeName statusCodeDescriptions[237] = {
const char * UA_StatusCode_name(UA_StatusCode code) {
for (size_t i = 0; i < statusCodeDescriptionsSize; ++i) {
- if (statusCodeDescriptions[i].code == code)
+ if (UA_StatusCode_isEqualTop(statusCodeDescriptions[i].code,code))
return statusCodeDescriptions[i].name;
}
return statusCodeDescriptions[statusCodeDescriptionsSize-1].name;
@@ -19491,7 +17911,7 @@ const char * UA_StatusCode_name(UA_StatusCode code) {
#endif
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/src/ua_util.c" ***********************************/
+/**** amalgamated original file "/src/ua_util.c" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -19504,7 +17924,6 @@ const char * UA_StatusCode_name(UA_StatusCode code) {
-
size_t
UA_readNumberWithBase(const UA_Byte *buf, size_t buflen, UA_UInt32 *number, UA_Byte base) {
UA_assert(buf);
@@ -19536,6 +17955,8 @@ UA_readNumber(const UA_Byte *buf, size_t buflen, UA_UInt32 *number) {
UA_StatusCode
UA_parseEndpointUrl(const UA_String *endpointUrl, UA_String *outHostname,
u16 *outPort, UA_String *outPath) {
+ UA_Boolean ipv6 = false;
+
/* Url must begin with "opc.tcp://" or opc.udp:// (if pubsub enabled) */
if(endpointUrl->length < 11) {
return UA_STATUSCODE_BADTCPENDPOINTURLINVALID;
@@ -19562,6 +17983,7 @@ UA_parseEndpointUrl(const UA_String *endpointUrl, UA_String *outHostname,
if(curr == endpointUrl->length)
return UA_STATUSCODE_BADTCPENDPOINTURLINVALID;
curr++;
+ ipv6 = true;
} else {
/* IPv4 or hostname: opc.tcp://something.something:1234/path */
for(; curr < endpointUrl->length; ++curr) {
@@ -19571,8 +17993,19 @@ UA_parseEndpointUrl(const UA_String *endpointUrl, UA_String *outHostname,
}
/* Set the hostname */
- outHostname->data = &endpointUrl->data[10];
- outHostname->length = curr - 10;
+ if(ipv6) {
+ /* Skip the ipv6 '[]' container for getaddrinfo() later */
+ outHostname->data = &endpointUrl->data[11];
+ outHostname->length = curr - 12;
+ } else {
+ outHostname->data = &endpointUrl->data[10];
+ outHostname->length = curr - 10;
+ }
+
+ /* Empty string? */
+ if(outHostname->length == 0)
+ outHostname->data = NULL;
+
if(curr == endpointUrl->length)
return UA_STATUSCODE_GOOD;
@@ -19581,7 +18014,8 @@ UA_parseEndpointUrl(const UA_String *endpointUrl, UA_String *outHostname,
if(++curr == endpointUrl->length)
return UA_STATUSCODE_BADTCPENDPOINTURLINVALID;
u32 largeNum;
- size_t progress = UA_readNumber(&endpointUrl->data[curr], endpointUrl->length - curr, &largeNum);
+ size_t progress = UA_readNumber(&endpointUrl->data[curr],
+ endpointUrl->length - curr, &largeNum);
if(progress == 0 || largeNum > 65535)
return UA_STATUSCODE_BADTCPENDPOINTURLINVALID;
/* Test if the end of a valid port was reached */
@@ -19605,6 +18039,10 @@ UA_parseEndpointUrl(const UA_String *endpointUrl, UA_String *outHostname,
if(endpointUrl->data[endpointUrl->length - 1] == '/')
outPath->length--;
+ /* Empty string? */
+ if(outPath->length == 0)
+ outPath->data = NULL;
+
return UA_STATUSCODE_GOOD;
}
@@ -19698,427 +18136,205 @@ UA_ByteString_fromBase64(UA_ByteString *bs,
return UA_STATUSCODE_GOOD;
}
+/* Key Value Map */
+
UA_StatusCode
-UA_NodeId_print(const UA_NodeId *id, UA_String *output) {
- UA_String_clear(output);
- if(!id)
+UA_KeyValueMap_setQualified(UA_KeyValuePair **map, size_t *mapSize,
+ const UA_QualifiedName *key,
+ const UA_Variant *value) {
+ /* Parameter exists already */
+ const UA_Variant *v = UA_KeyValueMap_getQualified(*map, *mapSize, key);
+ if(v) {
+ UA_Variant copyV;
+ UA_StatusCode res = UA_Variant_copy(v, &copyV);
+ if(res != UA_STATUSCODE_GOOD)
+ return res;
+ UA_Variant *target = (UA_Variant*)(uintptr_t)v;
+ UA_Variant_clear(target);
+ *target = copyV;
return UA_STATUSCODE_GOOD;
-
- char *nsStr = NULL;
- long snprintfLen = 0;
- size_t nsLen = 0;
- if(id->namespaceIndex != 0) {
- nsStr = (char*)UA_malloc(9+1); // strlen("ns=XXXXX;") = 9 + Nullbyte
- snprintfLen = UA_snprintf(nsStr, 10, "ns=%d;", id->namespaceIndex);
- if(snprintfLen < 0 || snprintfLen >= 10) {
- UA_free(nsStr);
- return UA_STATUSCODE_BADINTERNALERROR;
- }
- nsLen = (size_t)(snprintfLen);
- }
-
- UA_ByteString byteStr = UA_BYTESTRING_NULL;
- switch (id->identifierType) {
- case UA_NODEIDTYPE_NUMERIC:
- /* ns (2 byte, 65535) = 5 chars, numeric (4 byte, 4294967295) = 10
- * chars, delim = 1 , nullbyte = 1-> 17 chars */
- output->length = nsLen + 2 + 10 + 1;
- output->data = (UA_Byte*)UA_malloc(output->length);
- if(output->data == NULL) {
- output->length = 0;
- UA_free(nsStr);
- return UA_STATUSCODE_BADOUTOFMEMORY;
- }
- snprintfLen = UA_snprintf((char*)output->data, output->length, "%si=%lu",
- nsLen > 0 ? nsStr : "",
- (unsigned long )id->identifier.numeric);
- break;
- case UA_NODEIDTYPE_STRING:
- /* ns (16bit) = 5 chars, strlen + nullbyte */
- output->length = nsLen + 2 + id->identifier.string.length + 1;
- output->data = (UA_Byte*)UA_malloc(output->length);
- if(output->data == NULL) {
- output->length = 0;
- UA_free(nsStr);
- return UA_STATUSCODE_BADOUTOFMEMORY;
- }
- snprintfLen = UA_snprintf((char*)output->data, output->length, "%ss=%.*s",
- nsLen > 0 ? nsStr : "", (int)id->identifier.string.length,
- id->identifier.string.data);
- break;
- case UA_NODEIDTYPE_GUID:
- /* ns (16bit) = 5 chars + strlen(A123456C-0ABC-1A2B-815F-687212AAEE1B)=36 + nullbyte */
- output->length = nsLen + 2 + 36 + 1;
- output->data = (UA_Byte*)UA_malloc(output->length);
- if(output->data == NULL) {
- output->length = 0;
- UA_free(nsStr);
- return UA_STATUSCODE_BADOUTOFMEMORY;
- }
- snprintfLen = UA_snprintf((char*)output->data, output->length,
- "%sg=" UA_PRINTF_GUID_FORMAT, nsLen > 0 ? nsStr : "",
- UA_PRINTF_GUID_DATA(id->identifier.guid));
- break;
- case UA_NODEIDTYPE_BYTESTRING:
- UA_ByteString_toBase64(&id->identifier.byteString, &byteStr);
- /* ns (16bit) = 5 chars + LEN + nullbyte */
- output->length = nsLen + 2 + byteStr.length + 1;
- output->data = (UA_Byte*)UA_malloc(output->length);
- if(output->data == NULL) {
- output->length = 0;
- UA_String_deleteMembers(&byteStr);
- UA_free(nsStr);
- return UA_STATUSCODE_BADOUTOFMEMORY;
- }
- snprintfLen = UA_snprintf((char*)output->data, output->length, "%sb=%.*s",
- nsLen > 0 ? nsStr : "",
- (int)byteStr.length, byteStr.data);
- UA_String_deleteMembers(&byteStr);
- break;
- }
- UA_free(nsStr);
-
- if(snprintfLen < 0 || snprintfLen >= (long) output->length) {
- UA_free(output->data);
- output->data = NULL;
- output->length = 0;
- return UA_STATUSCODE_BADINTERNALERROR;
}
- output->length = (size_t)snprintfLen;
-
- return UA_STATUSCODE_GOOD;
-}
-
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/src/ua_workqueue.c" ***********************************/
-
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- *
- * Copyright 2014-2018 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
- * Copyright 2014-2016 (c) Sten Grüner
- * Copyright 2015 (c) Chris Iatrou
- * Copyright 2015 (c) Nick Goossens
- * Copyright 2015 (c) Jörg Schüler-Maroldt
- * Copyright 2015-2016 (c) Oleksiy Vasylyev
- * Copyright 2016-2017 (c) Florian Palm
- * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
- * Copyright 2016 (c) Lorenz Haas
- * Copyright 2017 (c) Jonas Green
- */
-
-void UA_WorkQueue_init(UA_WorkQueue *wq) {
- /* Initialized the linked list for delayed callbacks */
- SIMPLEQ_INIT(&wq->delayedCallbacks);
-
-#if UA_MULTITHREADING >= 200
- wq->delayedCallbacks_checkpoint = NULL;
- UA_LOCK_INIT(wq->delayedCallbacks_accessMutex)
-
- /* Initialize the dispatch queue for worker threads */
- SIMPLEQ_INIT(&wq->dispatchQueue);
- UA_LOCK_INIT(wq->dispatchQueue_accessMutex)
- pthread_cond_init(&wq->dispatchQueue_condition, NULL);
- UA_LOCK_INIT(wq->dispatchQueue_conditionMutex)
-#endif
+ /* Append to the array */
+ UA_KeyValuePair pair;
+ pair.key = *key;
+ pair.value = *value;
+ return UA_Array_appendCopy((void**)map, mapSize, &pair,
+ &UA_TYPES[UA_TYPES_KEYVALUEPAIR]);
}
-#if UA_MULTITHREADING >= 200
-/* Forward declaration */
-static void UA_WorkQueue_manuallyProcessDelayed(UA_WorkQueue *wq);
-#endif
-
-void UA_WorkQueue_cleanup(UA_WorkQueue *wq) {
-#if UA_MULTITHREADING >= 200
- /* Shut down workers */
- UA_WorkQueue_stop(wq);
-
- /* Execute remaining work in the dispatch queue */
- while(true) {
- UA_LOCK(wq->dispatchQueue_accessMutex);
- UA_DelayedCallback *dc = SIMPLEQ_FIRST(&wq->dispatchQueue);
- if(!dc) {
- UA_UNLOCK(wq->dispatchQueue_accessMutex);
- break;
- }
- SIMPLEQ_REMOVE_HEAD(&wq->dispatchQueue, next);
- UA_UNLOCK(wq->dispatchQueue_accessMutex);
- dc->callback(dc->application, dc->data);
- UA_free(dc);
- }
-#endif
-
- /* All workers are shut down. Execute remaining delayed work here. */
- UA_WorkQueue_manuallyProcessDelayed(wq);
-
-#if UA_MULTITHREADING >= 200
- wq->delayedCallbacks_checkpoint = NULL;
- UA_LOCK_DESTROY(wq->dispatchQueue_accessMutex);
- pthread_cond_destroy(&wq->dispatchQueue_condition);
- UA_LOCK_DESTROY(wq->dispatchQueue_conditionMutex);
- UA_LOCK_DESTROY(wq->delayedCallbacks_accessMutex);
-#endif
+UA_StatusCode
+UA_KeyValueMap_set(UA_KeyValuePair **map, size_t *mapSize,
+ const char *key, const UA_Variant *value) {
+ UA_QualifiedName qnKey;
+ qnKey.namespaceIndex = 0;
+ qnKey.name = UA_STRING((char*)(uintptr_t)key);
+ return UA_KeyValueMap_setQualified(map, mapSize, &qnKey, value);
}
-/***********/
-/* Workers */
-/***********/
-
-#if UA_MULTITHREADING >= 200
-
-static void *
-workerLoop(UA_Worker *worker) {
- UA_WorkQueue *wq = worker->queue;
- UA_UInt32 *counter = &worker->counter;
- volatile UA_Boolean *running = &worker->running;
-
- /* Initialize the (thread local) random seed with the ram address
- * of the worker. Not for security-critical entropy! */
- UA_random_seed((uintptr_t)worker);
+const UA_Variant *
+UA_KeyValueMap_getQualified(UA_KeyValuePair *map, size_t mapSize,
+ const UA_QualifiedName *key) {
+ for(size_t i = 0; i < mapSize; i++) {
+ if(map[i].key.namespaceIndex == key->namespaceIndex &&
+ UA_String_equal(&map[i].key.name, &key->name))
+ return &map[i].value;
- while(*running) {
- UA_atomic_addUInt32(counter, 1);
-
- /* Remove a callback from the queue */
- UA_LOCK(wq->dispatchQueue_accessMutex);
- UA_DelayedCallback *dc = SIMPLEQ_FIRST(&wq->dispatchQueue);
- if(dc)
- SIMPLEQ_REMOVE_HEAD(&wq->dispatchQueue, next);
- UA_UNLOCK(wq->dispatchQueue_accessMutex);
-
- /* Nothing to do. Sleep until a callback is dispatched */
- if(!dc) {
- UA_LOCK(wq->dispatchQueue_conditionMutex);
- pthread_cond_wait(&wq->dispatchQueue_condition,
- &wq->dispatchQueue_conditionMutex);
- UA_UNLOCK(wq->dispatchQueue_conditionMutex);
- continue;
- }
-
- /* Execute */
- if(dc->callback)
- dc->callback(dc->application, dc->data);
- UA_free(dc);
}
-
return NULL;
}
-/* Can be called repeatedly and starts additional workers */
-UA_StatusCode
-UA_WorkQueue_start(UA_WorkQueue *wq, size_t workersCount) {
- if(wq->workersSize > 0 || workersCount == 0)
- return UA_STATUSCODE_BADINTERNALERROR;
-
- /* Create the worker array */
- wq->workers = (UA_Worker*)UA_calloc(workersCount, sizeof(UA_Worker));
- if(!wq->workers)
- return UA_STATUSCODE_BADOUTOFMEMORY;
- wq->workersSize = workersCount;
-
- /* Spin up the workers */
- for(size_t i = 0; i < workersCount; ++i) {
- UA_Worker *w = &wq->workers[i];
- w->queue = wq;
- w->counter = 0;
- w->running = true;
- pthread_create(&w->thread, NULL, (void* (*)(void*))workerLoop, w);
- }
- return UA_STATUSCODE_GOOD;
+const UA_Variant *
+UA_KeyValueMap_get(UA_KeyValuePair *map, size_t mapSize,
+ const char *key) {
+ UA_QualifiedName qnKey;
+ qnKey.namespaceIndex = 0;
+ qnKey.name = UA_STRING((char*)(uintptr_t)key);
+ return UA_KeyValueMap_getQualified(map, mapSize, &qnKey);
}
-void UA_WorkQueue_stop(UA_WorkQueue *wq) {
- if(wq->workersSize == 0)
- return;
-
- /* Signal the workers to stop */
- for(size_t i = 0; i < wq->workersSize; ++i)
- wq->workers[i].running = false;
-
- /* Wake up all workers */
- pthread_cond_broadcast(&wq->dispatchQueue_condition);
-
- /* Wait for the workers to finish, then clean up */
- for(size_t i = 0; i < wq->workersSize; ++i)
- pthread_join(wq->workers[i].thread, NULL);
-
- UA_free(wq->workers);
- wq->workers = NULL;
- wq->workersSize = 0;
+/* Returns NULL if the parameter is not defined or not of the right datatype */
+const UA_Variant *
+UA_KeyValueMap_getScalar(UA_KeyValuePair *map, size_t mapSize,
+ const char *key, const UA_DataType *type) {
+ const UA_Variant *v = UA_KeyValueMap_get(map, mapSize, key);
+ if(!v || !UA_Variant_hasScalarType(v, type))
+ return NULL;
+ return v;
}
-void UA_WorkQueue_enqueue(UA_WorkQueue *wq, UA_ApplicationCallback cb,
- void *application, void *data) {
- UA_DelayedCallback *dc = (UA_DelayedCallback*)UA_malloc(sizeof(UA_DelayedCallback));
- if(!dc) {
- cb(application, data); /* Execute immediately if the memory could not be allocated */
- return;
- }
-
- dc->callback = cb;
- dc->application = application;
- dc->data = data;
-
- /* Enqueue for the worker threads */
- UA_LOCK(wq->dispatchQueue_accessMutex);
- SIMPLEQ_INSERT_TAIL(&wq->dispatchQueue, dc, next);
- UA_UNLOCK(wq->dispatchQueue_accessMutex);
-
- /* Wake up sleeping workers */
- pthread_cond_broadcast(&wq->dispatchQueue_condition);
+const UA_Variant *
+UA_KeyValueMap_getArray(UA_KeyValuePair *map, size_t mapSize,
+ const char *key, const UA_DataType *type) {
+ const UA_Variant *v = UA_KeyValueMap_get(map, mapSize, key);
+ if(!v || !UA_Variant_hasArrayType(v, type))
+ return NULL;
+ return v;
}
-#endif
-
-/*********************/
-/* Delayed Callbacks */
-/*********************/
-
-#if UA_MULTITHREADING >= 200
-
-/* Delayed Callbacks are called only when all callbacks that were dispatched
- * prior are finished. After every UA_MAX_DELAYED_SAMPLE delayed Callbacks that
- * were added to the queue, we sample the counters from the workers. The
- * counters are compared to the last counters that were sampled. If every worker
- * has proceeded the counter, then we know that all delayed callbacks prior to
- * the last sample-point are safe to execute. */
-
-/* Sample the worker counter for every nth delayed callback. This is used to
- * test that all workers have **finished** their current job before the delayed
- * callback is processed. */
-#define UA_MAX_DELAYED_SAMPLE 100
+void
+UA_KeyValueMap_deleteQualified(UA_KeyValuePair **map, size_t *mapSize,
+ const UA_QualifiedName *key) {
+ UA_KeyValuePair *m = *map;
+ size_t s = *mapSize;
+ for(size_t i = 0; i < s; i++) {
+ if(m[i].key.namespaceIndex != key->namespaceIndex ||
+ !UA_String_equal(&m[i].key.name, &key->name))
+ continue;
-/* Call only with a held mutex for the delayed callbacks */
-static void
-dispatchDelayedCallbacks(UA_WorkQueue *wq, UA_DelayedCallback *cb) {
- /* Are callbacks before the last checkpoint ready? */
- for(size_t i = 0; i < wq->workersSize; ++i) {
- if(wq->workers[i].counter == wq->workers[i].checkpointCounter)
- return;
- }
+ /* Clean the pair */
+ UA_KeyValuePair_clear(&m[i]);
- /* Dispatch all delayed callbacks up to the checkpoint.
- * TODO: Move over the entire queue up to the checkpoint in one step. */
- if(wq->delayedCallbacks_checkpoint != NULL) {
- UA_DelayedCallback *iter, *tmp_iter;
- SIMPLEQ_FOREACH_SAFE(iter, &wq->delayedCallbacks, next, tmp_iter) {
- UA_LOCK(wq->dispatchQueue_accessMutex);
- SIMPLEQ_INSERT_TAIL(&wq->dispatchQueue, iter, next);
- UA_UNLOCK(wq->dispatchQueue_accessMutex);
- if(iter == wq->delayedCallbacks_checkpoint)
- break;
+ /* Move the last pair to fill the empty slot */
+ if(s > 1 && i < s - 1) {
+ m[i] = m[s-1];
+ UA_KeyValuePair_init(&m[s-1]);
}
- }
- /* Create the new sample point */
- for(size_t i = 0; i < wq->workersSize; ++i)
- wq->workers[i].checkpointCounter = wq->workers[i].counter;
- wq->delayedCallbacks_checkpoint = cb;
-}
-
-#endif
-
-void
-UA_WorkQueue_enqueueDelayed(UA_WorkQueue *wq, UA_DelayedCallback *cb) {
-#if UA_MULTITHREADING >= 200
- UA_LOCK(wq->dispatchQueue_accessMutex);
-#endif
-
- SIMPLEQ_INSERT_HEAD(&wq->delayedCallbacks, cb, next);
-
-#if UA_MULTITHREADING >= 200
- wq->delayedCallbacks_sinceDispatch++;
- if(wq->delayedCallbacks_sinceDispatch > UA_MAX_DELAYED_SAMPLE) {
- dispatchDelayedCallbacks(wq, cb);
- wq->delayedCallbacks_sinceDispatch = 0;
+ UA_StatusCode res = UA_Array_resize((void**)map, mapSize, *mapSize-1,
+ &UA_TYPES[UA_TYPES_KEYVALUEPAIR]);
+ (void)res;
+ *mapSize = s - 1; /* In case resize fails, keep the longer original
+ * array around. Resize never fails when reducing
+ * the size to zero. Reduce the size integer in
+ * any case. */
+ return;
}
-
- UA_UNLOCK(wq->dispatchQueue_accessMutex);
-#endif
}
-/* Assumes all workers are shut down */
-void UA_WorkQueue_manuallyProcessDelayed(UA_WorkQueue *wq) {
- UA_DelayedCallback *dc, *dc_tmp;
- SIMPLEQ_FOREACH_SAFE(dc, &wq->delayedCallbacks, next, dc_tmp) {
- SIMPLEQ_REMOVE_HEAD(&wq->delayedCallbacks, next);
- if(dc->callback)
- dc->callback(dc->application, dc->data);
- UA_free(dc);
- }
-#if UA_MULTITHREADING >= 200
- wq->delayedCallbacks_checkpoint = NULL;
-#endif
+void
+UA_KeyValueMap_delete(UA_KeyValuePair **map, size_t *mapSize,
+ const char *key) {
+ UA_QualifiedName qnKey;
+ qnKey.namespaceIndex = 0;
+ qnKey.name = UA_STRING((char*)(uintptr_t)key);
+ UA_KeyValueMap_deleteQualified(map, mapSize, &qnKey);
}
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/src/ua_timer.c" ***********************************/
+/**** amalgamated original file "/src/ua_timer.c" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
- * Copyright 2017, 2018 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
+ * Copyright 2017, 2018, 2021 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
* Copyright 2017 (c) Stefan Profanter, fortiss GmbH
*/
-struct UA_TimerEntry {
- ZIP_ENTRY(UA_TimerEntry) zipfields;
- UA_DateTime nextTime; /* The next time when the callback
- * is to be executed */
- UA_UInt64 interval; /* Interval in 100ns resolution */
- UA_Boolean repeated; /* Repeated callback? */
-
- UA_ApplicationCallback callback;
- void *application;
- void *data;
-
- ZIP_ENTRY(UA_TimerEntry) idZipfields;
- UA_UInt64 id; /* Id of the entry */
-};
-
/* There may be several entries with the same nextTime in the tree. We give them
* an absolute order by considering the memory address to break ties. Because of
* this, the nextTime property cannot be used to lookup specific entries. */
-static enum ZIP_CMP
+static enum aa_cmp
cmpDateTime(const UA_DateTime *a, const UA_DateTime *b) {
if(*a < *b)
- return ZIP_CMP_LESS;
+ return AA_CMP_LESS;
if(*a > *b)
- return ZIP_CMP_MORE;
+ return AA_CMP_MORE;
if(a == b)
- return ZIP_CMP_EQ;
+ return AA_CMP_EQ;
if(a < b)
- return ZIP_CMP_LESS;
- return ZIP_CMP_MORE;
+ return AA_CMP_LESS;
+ return AA_CMP_MORE;
}
-ZIP_PROTTYPE(UA_TimerZip, UA_TimerEntry, UA_DateTime)
-ZIP_IMPL(UA_TimerZip, UA_TimerEntry, zipfields, UA_DateTime, nextTime, cmpDateTime)
-
/* The identifiers of entries are unique */
-static enum ZIP_CMP
+static enum aa_cmp
cmpId(const UA_UInt64 *a, const UA_UInt64 *b) {
if(*a < *b)
- return ZIP_CMP_LESS;
+ return AA_CMP_LESS;
if(*a == *b)
- return ZIP_CMP_EQ;
- return ZIP_CMP_MORE;
+ return AA_CMP_EQ;
+ return AA_CMP_MORE;
}
-ZIP_PROTTYPE(UA_TimerIdZip, UA_TimerEntry, UA_UInt64)
-ZIP_IMPL(UA_TimerIdZip, UA_TimerEntry, idZipfields, UA_UInt64, id, cmpId)
+static UA_DateTime
+calculateNextTime(UA_DateTime currentTime, UA_DateTime baseTime,
+ UA_DateTime interval) {
+ /* Take the difference between current and base time */
+ UA_DateTime diffCurrentTimeBaseTime = currentTime - baseTime;
+
+ /* Take modulo of the diff time with the interval. This is the duration we
+ * are already "into" the current interval. Subtract it from (current +
+ * interval) to get the next execution time. */
+ UA_DateTime cycleDelay = diffCurrentTimeBaseTime % interval;
+
+ /* Handle the special case where the baseTime is in the future */
+ if(UA_UNLIKELY(cycleDelay < 0))
+ cycleDelay += interval;
+
+ return currentTime + interval - cycleDelay;
+}
void
UA_Timer_init(UA_Timer *t) {
memset(t, 0, sizeof(UA_Timer));
+ aa_init(&t->root,
+ (enum aa_cmp (*)(const void*, const void*))cmpDateTime,
+ offsetof(UA_TimerEntry, treeEntry),
+ offsetof(UA_TimerEntry, nextTime));
+ aa_init(&t->idRoot,
+ (enum aa_cmp (*)(const void*, const void*))cmpId,
+ offsetof(UA_TimerEntry, idTreeEntry),
+ offsetof(UA_TimerEntry, id));
+ UA_LOCK_INIT(&t->timerMutex);
+}
+
+void
+UA_Timer_addTimerEntry(UA_Timer *t, UA_TimerEntry *te, UA_UInt64 *callbackId) {
+ UA_LOCK(&t->timerMutex);
+ te->id = ++t->idCounter;
+ if(callbackId)
+ *callbackId = te->id;
+ aa_insert(&t->root, te);
+ aa_insert(&t->idRoot, te);
+ UA_UNLOCK(&t->timerMutex);
}
static UA_StatusCode
-addCallback(UA_Timer *t, UA_ApplicationCallback callback, void *application, void *data,
- UA_DateTime nextTime, UA_UInt64 interval, UA_Boolean repeated,
- UA_UInt64 *callbackId) {
+addCallback(UA_Timer *t, UA_ApplicationCallback callback, void *application,
+ void *data, UA_DateTime nextTime, UA_UInt64 interval,
+ UA_TimerPolicy timerPolicy, UA_UInt64 *callbackId) {
/* A callback method needs to be present */
if(!callback)
return UA_STATUSCODE_BADINTERNALERROR;
@@ -20134,15 +18350,15 @@ addCallback(UA_Timer *t, UA_ApplicationCallback callback, void *application, voi
te->callback = callback;
te->application = application;
te->data = data;
- te->repeated = repeated;
te->nextTime = nextTime;
+ te->timerPolicy = timerPolicy;
/* Set the output identifier */
if(callbackId)
*callbackId = te->id;
- ZIP_INSERT(UA_TimerZip, &t->root, te, ZIP_FFS32(UA_UInt32_random()));
- ZIP_INSERT(UA_TimerIdZip, &t->idRoot, te, ZIP_RANK(te, zipfields));
+ aa_insert(&t->root, te);
+ aa_insert(&t->idRoot, te);
return UA_STATUSCODE_GOOD;
}
@@ -20150,7 +18366,12 @@ UA_StatusCode
UA_Timer_addTimedCallback(UA_Timer *t, UA_ApplicationCallback callback,
void *application, void *data, UA_DateTime date,
UA_UInt64 *callbackId) {
- return addCallback(t, callback, application, data, date, 0, false, callbackId);
+ UA_LOCK(&t->timerMutex);
+ UA_StatusCode res = addCallback(t, callback, application, data, date,
+ 0, UA_TIMER_HANDLE_CYCLEMISS_WITH_CURRENTTIME,
+ callbackId);
+ UA_UNLOCK(&t->timerMutex);
+ return res;
}
/* Adding repeated callbacks: Add an entry with the "nextTime" timestamp in the
@@ -20159,97 +18380,174 @@ UA_Timer_addTimedCallback(UA_Timer *t, UA_ApplicationCallback callback,
UA_StatusCode
UA_Timer_addRepeatedCallback(UA_Timer *t, UA_ApplicationCallback callback,
void *application, void *data, UA_Double interval_ms,
+ UA_DateTime *baseTime, UA_TimerPolicy timerPolicy,
UA_UInt64 *callbackId) {
/* The interval needs to be positive */
if(interval_ms <= 0.0)
return UA_STATUSCODE_BADINTERNALERROR;
-
UA_UInt64 interval = (UA_UInt64)(interval_ms * UA_DATETIME_MSEC);
- UA_DateTime nextTime = UA_DateTime_nowMonotonic() + (UA_DateTime)interval;
- return addCallback(t, callback, application, data, nextTime,
- interval, true, callbackId);
+ if(interval == 0)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ /* Compute the first time for execution */
+ UA_DateTime currentTime = UA_DateTime_nowMonotonic();
+ UA_DateTime nextTime;
+ if(baseTime == NULL) {
+ /* Use "now" as the basetime */
+ nextTime = currentTime + (UA_DateTime)interval;
+ } else {
+ nextTime = calculateNextTime(currentTime, *baseTime, (UA_DateTime)interval);
+ }
+
+ UA_LOCK(&t->timerMutex);
+ UA_StatusCode res = addCallback(t, callback, application, data, nextTime,
+ interval, timerPolicy, callbackId);
+ UA_UNLOCK(&t->timerMutex);
+ return res;
}
UA_StatusCode
-UA_Timer_changeRepeatedCallbackInterval(UA_Timer *t, UA_UInt64 callbackId,
- UA_Double interval_ms) {
+UA_Timer_changeRepeatedCallback(UA_Timer *t, UA_UInt64 callbackId,
+ UA_Double interval_ms, UA_DateTime *baseTime,
+ UA_TimerPolicy timerPolicy) {
/* The interval needs to be positive */
if(interval_ms <= 0.0)
return UA_STATUSCODE_BADINTERNALERROR;
+ UA_UInt64 interval = (UA_UInt64)(interval_ms * UA_DATETIME_MSEC);
+ if(interval == 0)
+ return UA_STATUSCODE_BADINTERNALERROR;
- /* Remove from the sorted list */
- UA_TimerEntry *te = ZIP_FIND(UA_TimerIdZip, &t->idRoot, &callbackId);
- if(!te)
+ UA_LOCK(&t->timerMutex);
+
+ /* Remove from the sorted tree */
+ UA_TimerEntry *te = (UA_TimerEntry*)aa_find(&t->idRoot, &callbackId);
+ if(!te) {
+ UA_UNLOCK(&t->timerMutex);
return UA_STATUSCODE_BADNOTFOUND;
+ }
+ aa_remove(&t->root, te);
- /* Set the repeated callback */
- ZIP_REMOVE(UA_TimerZip, &t->root, te);
- te->interval = (UA_UInt64)(interval_ms * UA_DATETIME_MSEC); /* in 100ns resolution */
- te->nextTime = UA_DateTime_nowMonotonic() + (UA_DateTime)te->interval;
- ZIP_INSERT(UA_TimerZip, &t->root, te, ZIP_RANK(te, zipfields));
+ /* Compute the next time for execution. The logic is identical to the
+ * creation of a new repeated callback. */
+ UA_DateTime currentTime = UA_DateTime_nowMonotonic();
+ if(baseTime == NULL) {
+ /* Use "now" as the basetime */
+ te->nextTime = currentTime + (UA_DateTime)interval;
+ } else {
+ te->nextTime = calculateNextTime(currentTime, *baseTime, (UA_DateTime)interval);
+ }
+
+ /* Update the remaining parameters and re-insert */
+ te->interval = interval;
+ te->timerPolicy = timerPolicy;
+ aa_insert(&t->root, te);
+
+ UA_UNLOCK(&t->timerMutex);
return UA_STATUSCODE_GOOD;
}
void
UA_Timer_removeCallback(UA_Timer *t, UA_UInt64 callbackId) {
- UA_TimerEntry *te = ZIP_FIND(UA_TimerIdZip, &t->idRoot, &callbackId);
- if(!te)
- return;
-
- ZIP_REMOVE(UA_TimerZip, &t->root, te);
- ZIP_REMOVE(UA_TimerIdZip, &t->idRoot, te);
- UA_free(te);
+ UA_LOCK(&t->timerMutex);
+ UA_TimerEntry *te = (UA_TimerEntry*)aa_find(&t->idRoot, &callbackId);
+ if(UA_LIKELY(te != NULL)) {
+ aa_remove(&t->root, te);
+ aa_remove(&t->idRoot, te);
+ UA_free(te);
+ }
+ UA_UNLOCK(&t->timerMutex);
}
UA_DateTime
UA_Timer_process(UA_Timer *t, UA_DateTime nowMonotonic,
UA_TimerExecutionCallback executionCallback,
void *executionApplication) {
+ UA_LOCK(&t->timerMutex);
UA_TimerEntry *first;
- while((first = ZIP_MIN(UA_TimerZip, &t->root)) &&
+ while((first = (UA_TimerEntry*)aa_min(&t->root)) &&
first->nextTime <= nowMonotonic) {
- ZIP_REMOVE(UA_TimerZip, &t->root, first);
+ aa_remove(&t->root, first);
/* Reinsert / remove to their new position first. Because the callback
* can interact with the zip tree and expects the same entries in the
* root and idRoot trees. */
- if(!first->repeated) {
- ZIP_REMOVE(UA_TimerIdZip, &t->idRoot, first);
- executionCallback(executionApplication, first->callback,
- first->application, first->data);
+ if(first->interval == 0) {
+ aa_remove(&t->idRoot, first);
+ if(first->callback) {
+ UA_UNLOCK(&t->timerMutex);
+ executionCallback(executionApplication, first->callback,
+ first->application, first->data);
+ UA_LOCK(&t->timerMutex);
+ }
UA_free(first);
continue;
}
/* Set the time for the next execution. Prevent an infinite loop by
- * forcing the next processing into the next iteration. */
- first->nextTime += (UA_Int64)first->interval;
- if(first->nextTime < nowMonotonic)
- first->nextTime = nowMonotonic + 1;
- ZIP_INSERT(UA_TimerZip, &t->root, first, ZIP_RANK(first, zipfields));
- executionCallback(executionApplication, first->callback,
- first->application, first->data);
+ * forcing the execution time in the next iteration.
+ *
+ * If the timer policy is "CurrentTime", then there is at least the
+ * interval between executions. This is used for Monitoreditems, for
+ * which the spec says: The sampling interval indicates the fastest rate
+ * at which the Server should sample its underlying source for data
+ * changes. (Part 4, 5.12.1.2) */
+ first->nextTime += (UA_DateTime)first->interval;
+ if(first->nextTime < nowMonotonic) {
+ if(first->timerPolicy == UA_TIMER_HANDLE_CYCLEMISS_WITH_BASETIME)
+ first->nextTime = calculateNextTime(nowMonotonic, first->nextTime,
+ (UA_DateTime)first->interval);
+ else
+ first->nextTime = nowMonotonic + (UA_DateTime)first->interval;
+ }
+
+ aa_insert(&t->root, first);
+
+ if(!first->callback)
+ continue;
+
+ /* Unlock the mutes before dropping into the callback. So that the timer
+ * itself can be edited within the callback. When we return, only the
+ * pointer to t must still exist. */
+ UA_ApplicationCallback cb = first->callback;
+ void *app = first->application;
+ void *data = first->data;
+ UA_UNLOCK(&t->timerMutex);
+ executionCallback(executionApplication, cb, app, data);
+ UA_LOCK(&t->timerMutex);
}
/* Return the timestamp of the earliest next callback */
- first = ZIP_MIN(UA_TimerZip, &t->root);
- return (first) ? first->nextTime : UA_INT64_MAX;
-}
-
-static void
-freeEntry(UA_TimerEntry *te, void *data) {
- UA_free(te);
+ first = (UA_TimerEntry*)aa_min(&t->root);
+ UA_DateTime next = (first) ? first->nextTime : UA_INT64_MAX;
+ if(next < nowMonotonic)
+ next = nowMonotonic;
+ UA_UNLOCK(&t->timerMutex);
+ return next;
}
void
-UA_Timer_deleteMembers(UA_Timer *t) {
- /* Free all nodes and reset the root */
- ZIP_ITER(UA_TimerZip, &t->root, freeEntry, NULL);
- ZIP_INIT(&t->root);
+UA_Timer_clear(UA_Timer *t) {
+ UA_LOCK(&t->timerMutex);
+
+ /* Free all entries */
+ UA_TimerEntry *top;
+ while((top = (UA_TimerEntry*)aa_min(&t->idRoot))) {
+ aa_remove(&t->idRoot, top);
+ UA_free(top);
+ }
+
+ /* Reset the trees to avoid future access */
+ t->root.root = NULL;
+ t->idRoot.root = NULL;
+
+ UA_UNLOCK(&t->timerMutex);
+#if UA_MULTITHREADING >= 100
+ UA_LOCK_DESTROY(&t->timerMutex);
+#endif
}
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/src/ua_connection.c" ***********************************/
+/**** amalgamated original file "/src/ua_connection.c" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -20300,8 +18598,13 @@ UA_Connection_sendError(UA_Connection *connection, UA_TcpErrorMessage *error) {
/* Encode and send the response */
UA_Byte *bufPos = msg.data;
const UA_Byte *bufEnd = &msg.data[msg.length];
- UA_TcpMessageHeader_encodeBinary(&header, &bufPos, bufEnd);
- UA_TcpErrorMessage_encodeBinary(error, &bufPos, bufEnd);
+ retval |= UA_encodeBinaryInternal(&header,
+ &UA_TRANSPORT[UA_TRANSPORT_TCPMESSAGEHEADER],
+ &bufPos, &bufEnd, NULL, NULL);
+ retval |= UA_encodeBinaryInternal(error,
+ &UA_TRANSPORT[UA_TRANSPORT_TCPERRORMESSAGE],
+ &bufPos, &bufEnd, NULL, NULL);
+ (void)retval; /* Encoding of these cannot fail */
msg.length = header.messageSize;
connection->send(connection, &msg);
}
@@ -20321,7 +18624,7 @@ UA_Connection_attachSecureChannel(UA_Connection *connection, UA_SecureChannel *c
UA_atomic_xchg((void**)&connection->channel, (void*)channel);
}
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/src/ua_securechannel.c" ***********************************/
+/**** amalgamated original file "/src/ua_securechannel.c" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -20342,7 +18645,7 @@ UA_Connection_attachSecureChannel(UA_Connection *connection, UA_SecureChannel *c
#define UA_BITMASK_MESSAGETYPE 0x00ffffffu
#define UA_BITMASK_CHUNKTYPE 0xff000000u
-const UA_ByteString UA_SECURITY_POLICY_NONE_URI =
+const UA_String UA_SECURITY_POLICY_NONE_URI =
{47, (UA_Byte *)"http://opcfoundation.org/UA/SecurityPolicy#None"};
#ifdef UA_ENABLE_UNIT_TEST_FAILURE_HOOKS
@@ -20355,8 +18658,9 @@ void UA_SecureChannel_init(UA_SecureChannel *channel,
const UA_ConnectionConfig *config) {
/* Linked lists are also initialized by zeroing out */
memset(channel, 0, sizeof(UA_SecureChannel));
- channel->state = UA_SECURECHANNELSTATE_CLOSED;
+ channel->state = UA_SECURECHANNELSTATE_FRESH;
SIMPLEQ_INIT(&channel->completeChunks);
+ SIMPLEQ_INIT(&channel->decryptedChunks);
SLIST_INIT(&channel->sessions);
channel->config = *config;
}
@@ -20366,52 +18670,53 @@ UA_SecureChannel_setSecurityPolicy(UA_SecureChannel *channel,
const UA_SecurityPolicy *securityPolicy,
const UA_ByteString *remoteCertificate) {
/* Is a policy already configured? */
- if(channel->securityPolicy) {
- UA_LOG_ERROR(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY,
- "Security policy already configured");
- return UA_STATUSCODE_BADINTERNALERROR;
- }
+ UA_CHECK_ERROR(!channel->securityPolicy, return UA_STATUSCODE_BADINTERNALERROR,
+ securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY,
+ "Security policy already configured");
- UA_StatusCode retval = securityPolicy->channelModule.
+ /* Create the context */
+ UA_StatusCode res = securityPolicy->channelModule.
newContext(securityPolicy, remoteCertificate, &channel->channelContext);
- if(retval != UA_STATUSCODE_GOOD) {
- UA_LOG_WARNING(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY,
- "Could not set up the SecureChannel context");
- return retval;
- }
-
- retval = UA_ByteString_copy(remoteCertificate, &channel->remoteCertificate);
- if(retval != UA_STATUSCODE_GOOD)
- return retval;
-
- UA_ByteString remoteCertificateThumbprint = {20, channel->remoteCertificateThumbprint};
- retval = securityPolicy->asymmetricModule.
+ res |= UA_ByteString_copy(remoteCertificate, &channel->remoteCertificate);
+ UA_CHECK_STATUS_WARN(res, return res, securityPolicy->logger,
+ UA_LOGCATEGORY_SECURITYPOLICY,
+ "Could not set up the SecureChannel context");
+
+ /* Compute the certificate thumbprint */
+ UA_ByteString remoteCertificateThumbprint =
+ {20, channel->remoteCertificateThumbprint};
+ res = securityPolicy->asymmetricModule.
makeCertificateThumbprint(securityPolicy, &channel->remoteCertificate,
&remoteCertificateThumbprint);
- if(retval != UA_STATUSCODE_GOOD) {
- UA_LOG_WARNING(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY,
- "Could not create the certificate thumbprint");
- return retval;
- }
+ UA_CHECK_STATUS_WARN(res, return res, securityPolicy->logger,
+ UA_LOGCATEGORY_SECURITYPOLICY,
+ "Could not create the certificate thumbprint");
+ /* Set the policy */
channel->securityPolicy = securityPolicy;
return UA_STATUSCODE_GOOD;
}
static void
+UA_Chunk_delete(UA_Chunk *chunk) {
+ if(chunk->copied)
+ UA_ByteString_clear(&chunk->bytes);
+ UA_free(chunk);
+}
+
+static void
deleteChunks(UA_ChunkQueue *queue) {
UA_Chunk *chunk;
while((chunk = SIMPLEQ_FIRST(queue))) {
- if(chunk->copied)
- UA_ByteString_deleteMembers(&chunk->bytes);
SIMPLEQ_REMOVE_HEAD(queue, pointers);
- UA_free(chunk);
+ UA_Chunk_delete(chunk);
}
}
void
UA_SecureChannel_deleteBuffered(UA_SecureChannel *channel) {
deleteChunks(&channel->completeChunks);
+ deleteChunks(&channel->decryptedChunks);
UA_ByteString_clear(&channel->incompleteChunk);
}
@@ -20427,12 +18732,16 @@ UA_SecureChannel_close(UA_SecureChannel *channel) {
UA_Connection_detachSecureChannel(channel->connection);
}
- /* Remove session pointers (not the sessions) and NULL the pointers back to
- * the SecureChannel in the Session */
+ /* Detach Sessions from the SecureChannel. This also removes outstanding
+ * Publish requests whose RequestId is valid only for the SecureChannel. */
UA_SessionHeader *sh;
while((sh = SLIST_FIRST(&channel->sessions))) {
- sh->channel = NULL;
- SLIST_REMOVE_HEAD(&channel->sessions, next);
+ if(sh->serverSession) {
+ UA_Session_detachFromSecureChannel((UA_Session *)sh);
+ } else {
+ sh->channel = NULL;
+ SLIST_REMOVE_HEAD(&channel->sessions, next);
+ }
}
/* Delete the channel context for the security policy */
@@ -20478,7 +18787,6 @@ UA_SecureChannel_processHELACK(UA_SecureChannel *channel,
return UA_STATUSCODE_BADINTERNALERROR;
channel->connection->state = UA_CONNECTIONSTATE_ESTABLISHED;
-
return UA_STATUSCODE_GOOD;
}
@@ -20487,23 +18795,18 @@ UA_StatusCode
UA_SecureChannel_sendAsymmetricOPNMessage(UA_SecureChannel *channel,
UA_UInt32 requestId, const void *content,
const UA_DataType *contentType) {
- if(channel->securityMode == UA_MESSAGESECURITYMODE_INVALID)
- return UA_STATUSCODE_BADSECURITYMODEREJECTED;
+ UA_CHECK(channel->securityMode != UA_MESSAGESECURITYMODE_INVALID,
+ return UA_STATUSCODE_BADSECURITYMODEREJECTED);
const UA_SecurityPolicy *sp = channel->securityPolicy;
- if(!sp)
- return UA_STATUSCODE_BADINTERNALERROR;
-
- UA_Connection *connection = channel->connection;
- if(!connection)
- return UA_STATUSCODE_BADINTERNALERROR;
+ UA_Connection *conn = channel->connection;
+ UA_CHECK_MEM(sp, return UA_STATUSCODE_BADINTERNALERROR);
+ UA_CHECK_MEM(conn, return UA_STATUSCODE_BADINTERNALERROR);
/* Allocate the message buffer */
UA_ByteString buf = UA_BYTESTRING_NULL;
- UA_StatusCode retval =
- connection->getSendBuffer(connection, channel->config.sendBufferSize, &buf);
- if(retval != UA_STATUSCODE_GOOD)
- return retval;
+ UA_StatusCode res = conn->getSendBuffer(conn, channel->config.sendBufferSize, &buf);
+ UA_CHECK_STATUS(res, return res);
/* Restrict buffer to the available space for the payload */
UA_Byte *buf_pos = buf.data;
@@ -20511,19 +18814,21 @@ UA_SecureChannel_sendAsymmetricOPNMessage(UA_SecureChannel *channel,
hideBytesAsym(channel, &buf_pos, &buf_end);
/* Encode the message type and content */
- UA_NodeId typeId = UA_NODEID_NUMERIC(0, contentType->binaryEncodingId);
- retval |= UA_encodeBinary(&typeId, &UA_TYPES[UA_TYPES_NODEID], &buf_pos, &buf_end, NULL, NULL);
- retval |= UA_encodeBinary(content, contentType, &buf_pos, &buf_end, NULL, NULL);
- if(retval != UA_STATUSCODE_GOOD) {
- connection->releaseSendBuffer(connection, &buf);
- return retval;
- }
+ res |= UA_NodeId_encodeBinary(&contentType->binaryEncodingId, &buf_pos, buf_end);
+ res |= UA_encodeBinaryInternal(content, contentType,
+ &buf_pos, &buf_end, NULL, NULL);
+ UA_CHECK_STATUS(res, conn->releaseSendBuffer(conn, &buf); return res);
const size_t securityHeaderLength = calculateAsymAlgSecurityHeaderLength(channel);
- /* Add padding to the chunk */
#ifdef UA_ENABLE_ENCRYPTION
- padChunkAsym(channel, &buf, securityHeaderLength, &buf_pos);
+ /* Add padding to the chunk. Also pad if the securityMode is SIGN_ONLY,
+ * since we are using asymmetric communication to exchange keys and thus
+ * need to encrypt. */
+ if(channel->securityMode != UA_MESSAGESECURITYMODE_NONE)
+ padChunk(channel, &channel->securityPolicy->asymmetricModule.cryptoModule,
+ &buf.data[UA_SECURECHANNEL_CHANNELHEADER_LENGTH + securityHeaderLength],
+ &buf_pos);
#endif
/* The total message length */
@@ -20532,42 +18837,34 @@ UA_SecureChannel_sendAsymmetricOPNMessage(UA_SecureChannel *channel,
if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGN ||
channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT)
total_length += sp->asymmetricModule.cryptoModule.signatureAlgorithm.
- getLocalSignatureSize(sp, channel->channelContext);
+ getLocalSignatureSize(channel->channelContext);
/* The total message length is known here which is why we encode the headers
* at this step and not earlier. */
- size_t finalLength = 0;
- retval = prependHeadersAsym(channel, buf.data, buf_end, total_length,
- securityHeaderLength, requestId, &finalLength);
- if(retval != UA_STATUSCODE_GOOD) {
- connection->releaseSendBuffer(connection, &buf);
- return retval;
- }
+ size_t encryptedLength = 0;
+ res = prependHeadersAsym(channel, buf.data, buf_end, total_length,
+ securityHeaderLength, requestId, &encryptedLength);
+ UA_CHECK_STATUS(res, conn->releaseSendBuffer(conn, &buf); return res);
#ifdef UA_ENABLE_ENCRYPTION
- retval = signAndEncryptAsym(channel, pre_sig_length, &buf, securityHeaderLength, total_length);
- if(retval != UA_STATUSCODE_GOOD) {
- connection->releaseSendBuffer(connection, &buf);
- return retval;
- }
+ res = signAndEncryptAsym(channel, pre_sig_length, &buf,
+ securityHeaderLength, total_length);
+ UA_CHECK_STATUS(res, conn->releaseSendBuffer(conn, &buf); return res);
#endif
/* Send the message, the buffer is freed in the network layer */
- buf.length = finalLength;
- retval = connection->send(connection, &buf);
+ buf.length = encryptedLength;
+ res = conn->send(conn, &buf);
#ifdef UA_ENABLE_UNIT_TEST_FAILURE_HOOKS
- retval |= sendAsym_sendFailure;
+ res |= sendAsym_sendFailure;
#endif
- return retval;
+ return res;
}
/* Will this chunk surpass the capacity of the SecureChannel for the message? */
static UA_StatusCode
-checkLimitsSym(UA_MessageContext *const mc, size_t *const bodyLength) {
- UA_Byte *buf_body_start = mc->messageBuffer.data + UA_SECURE_MESSAGE_HEADER_LENGTH;
- const UA_Byte *buf_body_end = mc->buf_pos;
- *bodyLength = (uintptr_t)buf_body_end - (uintptr_t)buf_body_start;
- mc->messageSizeSoFar += *bodyLength;
+adjustCheckMessageLimitsSym(UA_MessageContext *mc, size_t bodyLength) {
+ mc->messageSizeSoFar += bodyLength;
mc->chunksSoFar++;
UA_SecureChannel *channel = mc->channel;
@@ -20583,111 +18880,127 @@ checkLimitsSym(UA_MessageContext *const mc, size_t *const bodyLength) {
}
static UA_StatusCode
-encodeHeadersSym(UA_MessageContext *const messageContext, size_t totalLength) {
- UA_SecureChannel *channel = messageContext->channel;
- UA_Byte *header_pos = messageContext->messageBuffer.data;
+encodeHeadersSym(UA_MessageContext *mc, size_t totalLength) {
+ UA_SecureChannel *channel = mc->channel;
+ UA_Byte *header_pos = mc->messageBuffer.data;
UA_TcpMessageHeader header;
- header.messageTypeAndChunkType = messageContext->messageType;
+ header.messageTypeAndChunkType = mc->messageType;
header.messageSize = (UA_UInt32)totalLength;
- if(messageContext->final)
+ if(mc->final)
header.messageTypeAndChunkType += UA_CHUNKTYPE_FINAL;
else
header.messageTypeAndChunkType += UA_CHUNKTYPE_INTERMEDIATE;
UA_SequenceHeader seqHeader;
- seqHeader.requestId = messageContext->requestId;
+ seqHeader.requestId = mc->requestId;
seqHeader.sequenceNumber = UA_atomic_addUInt32(&channel->sendSequenceNumber, 1);
UA_StatusCode res = UA_STATUSCODE_GOOD;
- res |= UA_encodeBinary(&header, &UA_TRANSPORT[UA_TRANSPORT_TCPMESSAGEHEADER],
- &header_pos, &messageContext->buf_end, NULL, NULL);
- res |= UA_encodeBinary(&channel->securityToken.channelId, &UA_TYPES[UA_TYPES_UINT32],
- &header_pos, &messageContext->buf_end, NULL, NULL);
- res |= UA_encodeBinary(&channel->securityToken.tokenId, &UA_TYPES[UA_TYPES_UINT32],
- &header_pos, &messageContext->buf_end, NULL, NULL);
- res |= UA_encodeBinary(&seqHeader, &UA_TRANSPORT[UA_TRANSPORT_SEQUENCEHEADER],
- &header_pos, &messageContext->buf_end, NULL, NULL);
+ res |= UA_encodeBinaryInternal(&header, &UA_TRANSPORT[UA_TRANSPORT_TCPMESSAGEHEADER],
+ &header_pos, &mc->buf_end, NULL, NULL);
+ res |= UA_UInt32_encodeBinary(&channel->securityToken.channelId,
+ &header_pos, mc->buf_end);
+ res |= UA_UInt32_encodeBinary(&channel->securityToken.tokenId,
+ &header_pos, mc->buf_end);
+ res |= UA_encodeBinaryInternal(&seqHeader, &UA_TRANSPORT[UA_TRANSPORT_SEQUENCEHEADER],
+ &header_pos, &mc->buf_end, NULL, NULL);
return res;
}
static UA_StatusCode
-sendSymmetricChunk(UA_MessageContext *messageContext) {
- UA_SecureChannel *const channel = messageContext->channel;
- const UA_SecurityPolicy *securityPolicy = channel->securityPolicy;
- UA_Connection *const connection = channel->connection;
- if(!connection)
- return UA_STATUSCODE_BADINTERNALERROR;
+sendSymmetricChunk(UA_MessageContext *mc) {
+ UA_SecureChannel *channel = mc->channel;
+ const UA_SecurityPolicy *sp = channel->securityPolicy;
+ UA_Connection *connection = channel->connection;
+ UA_CHECK_MEM(connection, return UA_STATUSCODE_BADINTERNALERROR);
- size_t bodyLength = 0;
- UA_StatusCode res = checkLimitsSym(messageContext, &bodyLength);
- if(res != UA_STATUSCODE_GOOD)
- goto error;
+ /* The size of the message payload */
+ size_t bodyLength = (uintptr_t)mc->buf_pos -
+ (uintptr_t)&mc->messageBuffer.data[UA_SECURECHANNEL_SYMMETRIC_HEADER_TOTALLENGTH];
+
+ /* Early-declare variables so we can use a goto in the error case */
+ size_t total_length = 0;
+ size_t pre_sig_length = 0;
+
+ /* Check if chunk exceeds the limits for the overall message */
+ UA_StatusCode res = adjustCheckMessageLimitsSym(mc, bodyLength);
+ UA_CHECK_STATUS(res, goto error);
+
+ UA_LOG_TRACE_CHANNEL(sp->logger, channel,
+ "Send from a symmetric message buffer of length %lu "
+ "a message of header+payload length of %lu",
+ (long unsigned int)mc->messageBuffer.length,
+ (long unsigned int)
+ ((uintptr_t)mc->buf_pos - (uintptr_t)mc->messageBuffer.data));
- /* Add padding */
#ifdef UA_ENABLE_ENCRYPTION
- padChunkSym(messageContext, bodyLength);
+ /* Add padding if the message is encrypted */
+ if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT)
+ padChunk(channel, &sp->symmetricModule.cryptoModule,
+ &mc->messageBuffer.data[UA_SECURECHANNEL_SYMMETRIC_HEADER_UNENCRYPTEDLENGTH],
+ &mc->buf_pos);
#endif
- /* The total message length */
- size_t pre_sig_length = (uintptr_t)(messageContext->buf_pos) -
- (uintptr_t)messageContext->messageBuffer.data;
- size_t total_length = pre_sig_length;
+ /* Compute the total message length */
+ pre_sig_length = (uintptr_t)mc->buf_pos - (uintptr_t)mc->messageBuffer.data;
+ total_length = pre_sig_length;
if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGN ||
channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT)
- total_length += securityPolicy->symmetricModule.cryptoModule.signatureAlgorithm.
- getLocalSignatureSize(securityPolicy, channel->channelContext);
+ total_length += sp->symmetricModule.cryptoModule.signatureAlgorithm.
+ getLocalSignatureSize(channel->channelContext);
+
+ UA_LOG_TRACE_CHANNEL(sp->logger, channel,
+ "Send from a symmetric message buffer of length %lu "
+ "a message of length %lu",
+ (long unsigned int)mc->messageBuffer.length,
+ (long unsigned int)total_length);
+
/* Space for the padding and the signature have been reserved in setBufPos() */
UA_assert(total_length <= channel->config.sendBufferSize);
- /* For giving the buffer to the network layer */
- messageContext->messageBuffer.length = total_length;
+ /* Adjust the buffer size of the network layer */
+ mc->messageBuffer.length = total_length;
- UA_assert(res == UA_STATUSCODE_GOOD);
- res = encodeHeadersSym(messageContext, total_length);
- if(res != UA_STATUSCODE_GOOD)
- goto error;
+ /* Generate and encode the header for symmetric messages */
+ res = encodeHeadersSym(mc, total_length);
+ UA_CHECK_STATUS(res, goto error);
#ifdef UA_ENABLE_ENCRYPTION
- res = signChunkSym(messageContext, pre_sig_length);
- if(res != UA_STATUSCODE_GOOD)
- goto error;
-
- res = encryptChunkSym(messageContext, total_length);
- if(res != UA_STATUSCODE_GOOD)
- goto error;
+ /* Sign and encrypt the messge */
+ res = signAndEncryptSym(mc, pre_sig_length, total_length);
+ UA_CHECK_STATUS(res, goto error);
#endif
/* Send the chunk, the buffer is freed in the network layer */
- return connection->send(channel->connection, &messageContext->messageBuffer);
+ return connection->send(channel->connection, &mc->messageBuffer);
-error:
- connection->releaseSendBuffer(channel->connection, &messageContext->messageBuffer);
+ error:
+ /* Free the unused message buffer */
+ connection->releaseSendBuffer(channel->connection, &mc->messageBuffer);
return res;
}
/* Callback from the encoding layer. Send the chunk and replace the buffer. */
static UA_StatusCode
-sendSymmetricEncodingCallback(void *data, UA_Byte **buf_pos, const UA_Byte **buf_end) {
+sendSymmetricEncodingCallback(void *data, UA_Byte **buf_pos,
+ const UA_Byte **buf_end) {
/* Set buf values from encoding in the messagecontext */
UA_MessageContext *mc = (UA_MessageContext *)data;
mc->buf_pos = *buf_pos;
mc->buf_end = *buf_end;
/* Send out */
- UA_StatusCode retval = sendSymmetricChunk(mc);
- if(retval != UA_STATUSCODE_GOOD)
- return retval;
+ UA_StatusCode res = sendSymmetricChunk(mc);
+ UA_CHECK_STATUS(res, return res);
/* Set a new buffer for the next chunk */
- UA_Connection *connection = mc->channel->connection;
- if(!connection)
- return UA_STATUSCODE_BADINTERNALERROR;
+ UA_Connection *c = mc->channel->connection;
+ UA_CHECK_MEM(c, return UA_STATUSCODE_BADINTERNALERROR);
- retval = connection->getSendBuffer(connection, mc->channel->config.sendBufferSize,
- &mc->messageBuffer);
- if(retval != UA_STATUSCODE_GOOD)
- return retval;
+ res = c->getSendBuffer(c, mc->channel->config.sendBufferSize,
+ &mc->messageBuffer);
+ UA_CHECK_STATUS(res, return res);
/* Hide bytes for header, padding and signature */
setBufPos(mc);
@@ -20699,12 +19012,11 @@ sendSymmetricEncodingCallback(void *data, UA_Byte **buf_pos, const UA_Byte **buf
UA_StatusCode
UA_MessageContext_begin(UA_MessageContext *mc, UA_SecureChannel *channel,
UA_UInt32 requestId, UA_MessageType messageType) {
- UA_Connection *connection = channel->connection;
- if(!connection)
- return UA_STATUSCODE_BADINTERNALERROR;
+ UA_CHECK(messageType == UA_MESSAGETYPE_MSG || messageType == UA_MESSAGETYPE_CLO,
+ return UA_STATUSCODE_BADINTERNALERROR);
- if(messageType != UA_MESSAGETYPE_MSG && messageType != UA_MESSAGETYPE_CLO)
- return UA_STATUSCODE_BADINTERNALERROR;
+ UA_Connection *c = channel->connection;
+ UA_CHECK_MEM(c, return UA_STATUSCODE_BADINTERNALERROR);
/* Create the chunking info structure */
mc->channel = channel;
@@ -20716,11 +19028,9 @@ UA_MessageContext_begin(UA_MessageContext *mc, UA_SecureChannel *channel,
mc->messageType = messageType;
/* Allocate the message buffer */
- UA_StatusCode retval =
- connection->getSendBuffer(connection, channel->config.sendBufferSize,
- &mc->messageBuffer);
- if(retval != UA_STATUSCODE_GOOD)
- return retval;
+ UA_StatusCode res = c->getSendBuffer(c, channel->config.sendBufferSize,
+ &mc->messageBuffer);
+ UA_CHECK_STATUS(res, return res);
/* Hide bytes for header, padding and signature */
setBufPos(mc);
@@ -20730,11 +19040,12 @@ UA_MessageContext_begin(UA_MessageContext *mc, UA_SecureChannel *channel,
UA_StatusCode
UA_MessageContext_encode(UA_MessageContext *mc, const void *content,
const UA_DataType *contentType) {
- UA_StatusCode retval = UA_encodeBinary(content, contentType, &mc->buf_pos, &mc->buf_end,
- sendSymmetricEncodingCallback, mc);
- if(retval != UA_STATUSCODE_GOOD && mc->messageBuffer.length > 0)
+ UA_StatusCode res =
+ UA_encodeBinaryInternal(content, contentType, &mc->buf_pos, &mc->buf_end,
+ sendSymmetricEncodingCallback, mc);
+ if(res != UA_STATUSCODE_GOOD && mc->messageBuffer.length > 0)
UA_MessageContext_abort(mc);
- return retval;
+ return res;
}
UA_StatusCode
@@ -20763,22 +19074,20 @@ UA_SecureChannel_sendSymmetricMessage(UA_SecureChannel *channel, UA_UInt32 reque
return UA_STATUSCODE_BADCONNECTIONCLOSED;
UA_MessageContext mc;
- UA_StatusCode retval = UA_MessageContext_begin(&mc, channel, requestId, messageType);
- if(retval != UA_STATUSCODE_GOOD)
- return retval;
+ UA_StatusCode res = UA_MessageContext_begin(&mc, channel, requestId, messageType);
+ UA_CHECK_STATUS(res, return res);
/* Assert's required for clang-analyzer */
- UA_assert(mc.buf_pos == &mc.messageBuffer.data[UA_SECURE_MESSAGE_HEADER_LENGTH]);
+ UA_assert(mc.buf_pos ==
+ &mc.messageBuffer.data[UA_SECURECHANNEL_SYMMETRIC_HEADER_TOTALLENGTH]);
UA_assert(mc.buf_end <= &mc.messageBuffer.data[mc.messageBuffer.length]);
- UA_NodeId typeId = UA_NODEID_NUMERIC(0, payloadType->binaryEncodingId);
- retval = UA_MessageContext_encode(&mc, &typeId, &UA_TYPES[UA_TYPES_NODEID]);
- if(retval != UA_STATUSCODE_GOOD)
- return retval;
+ res = UA_MessageContext_encode(&mc, &payloadType->binaryEncodingId,
+ &UA_TYPES[UA_TYPES_NODEID]);
+ UA_CHECK_STATUS(res, return res);
- retval = UA_MessageContext_encode(&mc, payload, payloadType);
- if(retval != UA_STATUSCODE_GOOD)
- return retval;
+ res = UA_MessageContext_encode(&mc, payload, payloadType);
+ UA_CHECK_STATUS(res, return res);
return UA_MessageContext_finish(&mc);
}
@@ -20787,22 +19096,24 @@ UA_SecureChannel_sendSymmetricMessage(UA_SecureChannel *channel, UA_UInt32 reque
/* Receive and Process Messages */
/********************************/
+/* Does the sequence number match? Otherwise try to rollover. See Part 6,
+ * Section 6.7.2.4 of the standard. */
+#define UA_SEQUENCENUMBER_ROLLOVER 4294966271
+
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
static UA_StatusCode
processSequenceNumberSym(UA_SecureChannel *channel, UA_UInt32 sequenceNumber) {
- /* Failure mode hook for unit tests */
#ifdef UA_ENABLE_UNIT_TEST_FAILURE_HOOKS
+ /* Failure mode hook for unit tests */
if(processSym_seqNumberFailure != UA_STATUSCODE_GOOD)
return processSym_seqNumberFailure;
#endif
- /* Does the sequence number match? */
if(sequenceNumber != channel->receiveSequenceNumber + 1) {
- /* FIXME: Remove magic numbers :( */
- if(channel->receiveSequenceNumber + 1 > 4294966271 && sequenceNumber < 1024)
- channel->receiveSequenceNumber = sequenceNumber - 1; /* Roll over */
- else
+ if(channel->receiveSequenceNumber + 1 <= UA_SEQUENCENUMBER_ROLLOVER ||
+ sequenceNumber >= 1024)
return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
+ channel->receiveSequenceNumber = sequenceNumber - 1; /* Roll over */
}
++channel->receiveSequenceNumber;
return UA_STATUSCODE_GOOD;
@@ -20810,116 +19121,198 @@ processSequenceNumberSym(UA_SecureChannel *channel, UA_UInt32 sequenceNumber) {
#endif
static UA_StatusCode
-decryptVerifySymmetricChunk(UA_SecureChannel *channel, const UA_SecurityPolicy *sp,
- UA_Chunk *chunk, UA_UInt32 *requestId) {
- size_t offset = 8; /* Skip the message header */
+unpackPayloadOPN(UA_SecureChannel *channel, UA_Chunk *chunk, void *application) {
+ UA_assert(chunk->bytes.length >= UA_SECURECHANNEL_MESSAGE_MIN_LENGTH);
+ size_t offset = UA_SECURECHANNEL_MESSAGEHEADER_LENGTH; /* Skip the message header */
+ UA_UInt32 secureChannelId;
+ UA_StatusCode res = UA_UInt32_decodeBinary(&chunk->bytes, &offset, &secureChannelId);
+ UA_assert(res == UA_STATUSCODE_GOOD);
+
+ UA_AsymmetricAlgorithmSecurityHeader asymHeader;
+ res = UA_decodeBinaryInternal(&chunk->bytes, &offset, &asymHeader,
+ &UA_TRANSPORT[UA_TRANSPORT_ASYMMETRICALGORITHMSECURITYHEADER], NULL);
+ UA_CHECK_STATUS(res, return res);
+
+ if(asymHeader.senderCertificate.length > 0) {
+ if(channel->certificateVerification)
+ res = channel->certificateVerification->
+ verifyCertificate(channel->certificateVerification->context,
+ &asymHeader.senderCertificate);
+ else
+ res = UA_STATUSCODE_BADINTERNALERROR;
+ UA_CHECK_STATUS(res, goto error);
+ }
+
+ /* New channel, create a security policy context and attach */
+ if(!channel->securityPolicy) {
+ if(channel->processOPNHeader)
+ res = channel->processOPNHeader(application, channel, &asymHeader);
+ if(!channel->securityPolicy)
+ res = UA_STATUSCODE_BADINTERNALERROR;
+ UA_CHECK_STATUS(res, goto error);
+ }
+
+ /* On the client side, take the SecureChannelId from the first response */
+ if(secureChannelId != 0 && channel->securityToken.channelId == 0)
+ channel->securityToken.channelId = secureChannelId;
+
+#if !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
+ /* Check the ChannelId. Non-opened channels have the id zero. */
+ if(secureChannelId != channel->securityToken.channelId) {
+ res = UA_STATUSCODE_BADSECURECHANNELIDINVALID;
+ goto error;
+ }
+#endif
+
+ /* Check the header */
+ res = checkAsymHeader(channel, &asymHeader);
+ UA_AsymmetricAlgorithmSecurityHeader_clear(&asymHeader);
+ UA_CHECK_STATUS(res, return res);
+
+ /* Decrypt the chunk payload */
+ res = decryptAndVerifyChunk(channel,
+ &channel->securityPolicy->asymmetricModule.cryptoModule,
+ chunk->messageType, &chunk->bytes, offset);
+ UA_CHECK_STATUS(res, return res);
+
+ /* Decode the SequenceHeader */
+ UA_SequenceHeader sequenceHeader;
+ res = UA_decodeBinaryInternal(&chunk->bytes, &offset, &sequenceHeader,
+ &UA_TRANSPORT[UA_TRANSPORT_SEQUENCEHEADER], NULL);
+ UA_CHECK_STATUS(res, return res);
+
+ /* Set the sequence number for the channel from which to count up */
+ channel->receiveSequenceNumber = sequenceHeader.sequenceNumber;
+ chunk->requestId = sequenceHeader.requestId; /* Set the RequestId of the chunk */
+
+ /* Use only the payload */
+ chunk->bytes.data += offset;
+ chunk->bytes.length -= offset;
+ return UA_STATUSCODE_GOOD;
+
+error:
+ UA_AsymmetricAlgorithmSecurityHeader_clear(&asymHeader);
+ return res;
+}
+
+static UA_StatusCode
+unpackPayloadMSG(UA_SecureChannel *channel, UA_Chunk *chunk) {
+ UA_CHECK_MEM(channel->securityPolicy, return UA_STATUSCODE_BADINTERNALERROR);
+
+ UA_assert(chunk->bytes.length >= UA_SECURECHANNEL_MESSAGE_MIN_LENGTH);
+ size_t offset = UA_SECURECHANNEL_MESSAGEHEADER_LENGTH; /* Skip the message header */
UA_UInt32 secureChannelId;
- UA_UInt32 tokenId;
+ UA_UInt32 tokenId; /* SymmetricAlgorithmSecurityHeader */
UA_StatusCode res = UA_STATUSCODE_GOOD;
res |= UA_UInt32_decodeBinary(&chunk->bytes, &offset, &secureChannelId);
res |= UA_UInt32_decodeBinary(&chunk->bytes, &offset, &tokenId);
- if(res != UA_STATUSCODE_GOOD)
- return res;
+ UA_assert(offset == UA_SECURECHANNEL_MESSAGE_MIN_LENGTH);
+ UA_assert(res == UA_STATUSCODE_GOOD);
#if !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
/* Check the ChannelId. Non-opened channels have the id zero. */
- if(secureChannelId != channel->securityToken.channelId)
- return UA_STATUSCODE_BADSECURECHANNELIDINVALID;
+ UA_CHECK(secureChannelId == channel->securityToken.channelId,
+ return UA_STATUSCODE_BADSECURECHANNELIDINVALID);
#endif
/* Check (and revolve) the SecurityToken */
res = checkSymHeader(channel, tokenId);
- if(res != UA_STATUSCODE_GOOD)
- return res;
+ UA_CHECK_STATUS(res, return res);
/* Decrypt the chunk payload */
- if(!chunk->decrypted) {
- res = decryptAndVerifyChunk(channel, &sp->symmetricModule.cryptoModule,
- chunk->messageType, &chunk->bytes, offset);
- if(res != UA_STATUSCODE_GOOD)
- return res;
- chunk->decrypted = true;
- }
+ res = decryptAndVerifyChunk(channel,
+ &channel->securityPolicy->symmetricModule.cryptoModule,
+ chunk->messageType, &chunk->bytes, offset);
+ UA_CHECK_STATUS(res, return res);
/* Check the sequence number. Skip sequence number checking for fuzzer to
* improve coverage */
UA_SequenceHeader sequenceHeader;
- res = UA_SequenceHeader_decodeBinary(&chunk->bytes, &offset, &sequenceHeader);
+ res = UA_decodeBinaryInternal(&chunk->bytes, &offset, &sequenceHeader,
+ &UA_TRANSPORT[UA_TRANSPORT_SEQUENCEHEADER], NULL);
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
res |= processSequenceNumberSym(channel, sequenceHeader.sequenceNumber);
#endif
+ UA_CHECK_STATUS(res, return res);
- *requestId = sequenceHeader.requestId;
- return res;
+ chunk->requestId = sequenceHeader.requestId; /* Set the RequestId of the chunk */
+
+ /* Use only the payload */
+ chunk->bytes.data += offset;
+ chunk->bytes.length -= offset;
+ return UA_STATUSCODE_GOOD;
}
static UA_StatusCode
-assembleProcessMessage(UA_SecureChannel *channel, UA_ChunkQueue *chunks, size_t chunksSize,
- UA_UInt32 requestId, UA_MessageType messageType,
- void *application, UA_ProcessMessageCallback callback) {
- /* Only MSG and CLO messages at this point */
- UA_assert(messageType == UA_MESSAGETYPE_MSG ||
- messageType == UA_MESSAGETYPE_CLO);
+assembleProcessMessage(UA_SecureChannel *channel, void *application,
+ UA_ProcessMessageCallback callback) {
+ UA_Chunk *chunk = SIMPLEQ_FIRST(&channel->decryptedChunks);
+ UA_assert(chunk != NULL);
- /* Assemble message */
- UA_Chunk *chunk;
- UA_ByteString payload;
- if(chunksSize > 1) {
- /* Compute the full message length. Omit the MessageHeader and
- * SequenceHeader. */
- size_t messageLength = 0;
- SIMPLEQ_FOREACH(chunk, chunks, pointers)
- messageLength += chunk->bytes.length - 24;
-
- /* Test chunk count against the connection settings */
- if(channel->config.localMaxMessageSize != 0 &&
- messageLength > channel->config.localMaxMessageSize)
- return UA_STATUSCODE_BADRESPONSETOOLARGE;
-
- /* Allocate memory for the full message */
- UA_StatusCode res = UA_ByteString_allocBuffer(&payload, messageLength);
- if(res != UA_STATUSCODE_GOOD)
- return res;
-
- /* Assemble the full message */
- size_t curPos = 0;
- SIMPLEQ_FOREACH(chunk, chunks, pointers) {
- UA_assert(chunk->bytes.length > 24);
- memcpy(&payload.data[curPos], chunk->bytes.data + 24,
- chunk->bytes.length - 24);
- curPos += chunk->bytes.length - 24;
- }
-
- /* Process the message */
- callback(application, channel, messageType, requestId, &payload);
- UA_ByteString_deleteMembers(&payload);
- return UA_STATUSCODE_GOOD;
+ UA_StatusCode res = UA_STATUSCODE_GOOD;
+ if(chunk->chunkType == UA_CHUNKTYPE_FINAL) {
+ SIMPLEQ_REMOVE_HEAD(&channel->decryptedChunks, pointers);
+ UA_assert(chunk->chunkType == UA_CHUNKTYPE_FINAL);
+ res = callback(application, channel, chunk->messageType,
+ chunk->requestId, &chunk->bytes);
+ UA_Chunk_delete(chunk);
+ return res;
+ }
+
+ UA_UInt32 requestId = chunk->requestId;
+ UA_MessageType messageType = chunk->messageType;
+ UA_ChunkType chunkType = chunk->chunkType;
+ UA_assert(chunkType == UA_CHUNKTYPE_INTERMEDIATE);
+
+ size_t messageSize = 0;
+ SIMPLEQ_FOREACH(chunk, &channel->decryptedChunks, pointers) {
+ /* Consistency check */
+ if(requestId != chunk->requestId)
+ return UA_STATUSCODE_BADINTERNALERROR;
+ if(chunkType != chunk->chunkType && chunk->chunkType != UA_CHUNKTYPE_FINAL)
+ return UA_STATUSCODE_BADTCPMESSAGETYPEINVALID;
+ if(chunk->messageType != messageType)
+ return UA_STATUSCODE_BADTCPMESSAGETYPEINVALID;
+
+ /* Sum up the lengths */
+ messageSize += chunk->bytes.length;
+ if(chunk->chunkType == UA_CHUNKTYPE_FINAL)
+ break;
}
+
+ /* Allocate memory for the full message */
+ UA_ByteString payload;
+ res = UA_ByteString_allocBuffer(&payload, messageSize);
+ UA_CHECK_STATUS(res, return res);
- /* Hide the MessageHeader and SequenceHeader */
- chunk = SIMPLEQ_FIRST(chunks);
- payload = chunk->bytes;
- UA_assert(chunk->bytes.length > 24);
- payload.data += 24;
- payload.length -= 24;
+ /* Assemble the full message */
+ size_t offset = 0;
+ while(true) {
+ chunk = SIMPLEQ_FIRST(&channel->decryptedChunks);
+ memcpy(&payload.data[offset], chunk->bytes.data, chunk->bytes.length);
+ offset += chunk->bytes.length;
+ SIMPLEQ_REMOVE_HEAD(&channel->decryptedChunks, pointers);
+ UA_ChunkType ct = chunk->chunkType;
+ UA_Chunk_delete(chunk);
+ if(ct == UA_CHUNKTYPE_FINAL)
+ break;
+ }
- /* Process the message */
- callback(application, channel, messageType, requestId, &payload);
- return UA_STATUSCODE_GOOD;
+ /* Process the assembled message */
+ res = callback(application, channel, messageType, requestId, &payload);
+ UA_ByteString_clear(&payload);
+ return res;
}
static UA_StatusCode
-persistCompleteChunks(UA_SecureChannel *channel) {
+persistCompleteChunks(UA_ChunkQueue *queue) {
UA_Chunk *chunk;
- SIMPLEQ_FOREACH(chunk, &channel->completeChunks, pointers) {
+ SIMPLEQ_FOREACH(chunk, queue, pointers) {
if(chunk->copied)
continue;
UA_ByteString copy;
- UA_StatusCode retval = UA_ByteString_copy(&chunk->bytes, &copy);
- if(retval != UA_STATUSCODE_GOOD) {
- UA_SecureChannel_close(channel);
- return retval;
- }
+ UA_StatusCode res = UA_ByteString_copy(&chunk->bytes, &copy);
+ UA_CHECK_STATUS(res, return res);
chunk->bytes = copy;
chunk->copied = true;
}
@@ -20928,157 +19321,90 @@ persistCompleteChunks(UA_SecureChannel *channel) {
static UA_StatusCode
persistIncompleteChunk(UA_SecureChannel *channel, const UA_ByteString *buffer,
- size_t offset) {
+ size_t offset) {
UA_assert(channel->incompleteChunk.length == 0);
UA_assert(offset < buffer->length);
size_t length = buffer->length - offset;
- UA_StatusCode retval = UA_ByteString_allocBuffer(&channel->incompleteChunk, length);
- if(retval != UA_STATUSCODE_GOOD)
- return retval;
+ UA_StatusCode res = UA_ByteString_allocBuffer(&channel->incompleteChunk, length);
+ UA_CHECK_STATUS(res, return res);
memcpy(channel->incompleteChunk.data, &buffer->data[offset], length);
return UA_STATUSCODE_GOOD;
}
+/* Processes chunks and puts them into the payloads queue. Once a final chunk is
+ * put into the queue, the message is assembled and the callback is called. The
+ * queue will be cleared for the next message. */
static UA_StatusCode
-processSymmetricChunks(UA_SecureChannel *channel, UA_ChunkQueue *doneChunks,
- void *application, UA_ProcessMessageCallback callback) {
- /* Channel configured? */
- const UA_SecurityPolicy *sp = channel->securityPolicy;
- if(!sp)
- return UA_STATUSCODE_BADINTERNALERROR;
-
- /* Something to do? */
- UA_Chunk *chunk = SIMPLEQ_FIRST(&channel->completeChunks);
- if(!chunk)
- return UA_STATUSCODE_GOOD;
-
- /* Compare that the messageType until the final chunk is the same */
- UA_MessageType messageType = chunk->messageType;
-
- /* Do we have a complete message? */
- UA_ChunkType finalType = UA_CHUNKTYPE_INTERMEDIATE;
- size_t chunksSize = 0;
- UA_Chunk *finalChunk = NULL;
- SIMPLEQ_FOREACH(finalChunk, &channel->completeChunks, pointers) {
- chunksSize++;
- finalType = finalChunk->chunkType;
- if(finalChunk->messageType != messageType)
- return UA_STATUSCODE_BADTCPMESSAGETYPEINVALID;
- if(finalChunk->chunkType != UA_CHUNKTYPE_INTERMEDIATE)
- break;
- }
-
- /* Test chunk count against the connection settings */
- if(channel->config.localMaxChunkCount != 0 &&
- chunksSize > channel->config.localMaxChunkCount)
- return UA_STATUSCODE_BADRESPONSETOOLARGE;
-
- /* No complete mesage received */
- if(finalType == UA_CHUNKTYPE_INTERMEDIATE)
- return UA_STATUSCODE_GOOD;
-
- /* Abort: Remove all chunks for this message */
- if(finalType == UA_CHUNKTYPE_ABORT) {
- while((chunk = SIMPLEQ_FIRST(&channel->completeChunks))) {
- SIMPLEQ_REMOVE_HEAD(&channel->completeChunks, pointers);
- SIMPLEQ_INSERT_TAIL(doneChunks, chunk, pointers);
- if(chunk == finalChunk)
- break;
- }
- return UA_STATUSCODE_GOOD;
- }
-
- /* A complete message has been received */
- UA_assert(finalType == UA_CHUNKTYPE_FINAL);
-
- /* Decrypt and verify the message chunks */
- UA_Boolean first = true;
- UA_UInt32 messageRequestId = 0;
+processChunks(UA_SecureChannel *channel, void *application,
+ UA_ProcessMessageCallback callback) {
+ UA_Chunk *chunk;
UA_StatusCode res = UA_STATUSCODE_GOOD;
while((chunk = SIMPLEQ_FIRST(&channel->completeChunks))) {
- /* Move the chunks for this message out of the channel queue */
+ /* Remove from the complete-chunk queue */
SIMPLEQ_REMOVE_HEAD(&channel->completeChunks, pointers);
- SIMPLEQ_INSERT_TAIL(doneChunks, chunk, pointers);
- UA_UInt32 requestId;
- res = decryptVerifySymmetricChunk(channel, sp, chunk, &requestId);
- if(res != UA_STATUSCODE_GOOD)
- return res;
-
- /* Compare that the requestId is the same for all chunks */
- if(first) {
- messageRequestId = requestId;
- first = false;
- } else if(messageRequestId != requestId) {
- return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
+ /* Check, decrypt and unpack the payload */
+ if(chunk->messageType == UA_MESSAGETYPE_OPN) {
+ if(channel->state != UA_SECURECHANNELSTATE_OPEN &&
+ channel->state != UA_SECURECHANNELSTATE_OPN_SENT &&
+ channel->state != UA_SECURECHANNELSTATE_ACK_SENT)
+ res = UA_STATUSCODE_BADINVALIDSTATE;
+ else
+ res = unpackPayloadOPN(channel, chunk, application);
+ } else if(chunk->messageType == UA_MESSAGETYPE_MSG ||
+ chunk->messageType == UA_MESSAGETYPE_CLO) {
+ if(channel->state == UA_SECURECHANNELSTATE_CLOSED)
+ res = UA_STATUSCODE_BADSECURECHANNELCLOSED;
+ else
+ res = unpackPayloadMSG(channel, chunk);
+ } else {
+ chunk->bytes.data += UA_SECURECHANNEL_MESSAGEHEADER_LENGTH;
+ chunk->bytes.length -= UA_SECURECHANNEL_MESSAGEHEADER_LENGTH;
}
- if(chunk == finalChunk)
- break;
- }
- return assembleProcessMessage(channel, doneChunks, chunksSize, messageRequestId,
- messageType, application, callback);
-}
-
-static UA_StatusCode
-processCompleteChunks(UA_SecureChannel *channel, void *application,
- UA_ProcessMessageCallback callback) {
- UA_StatusCode res = UA_STATUSCODE_GOOD;
- UA_Chunk *chunk = SIMPLEQ_FIRST(&channel->completeChunks);
- while(chunk) {
- UA_ChunkQueue doneChunks;
- SIMPLEQ_INIT(&doneChunks);
- switch(chunk->messageType) {
- case UA_MESSAGETYPE_HEL:
- case UA_MESSAGETYPE_ACK:
- case UA_MESSAGETYPE_OPN:
- case UA_MESSAGETYPE_ERR:
- /* Chunks that are processed entirely by the application */
- SIMPLEQ_REMOVE_HEAD(&channel->completeChunks, pointers);
- SIMPLEQ_INSERT_TAIL(&doneChunks, chunk, pointers);
- callback(application, channel, chunk->messageType, 0, &chunk->bytes);
- break;
- default: /* MSG and CLO */
- res = processSymmetricChunks(channel, &doneChunks, application, callback);
- break;
+ if(res != UA_STATUSCODE_GOOD) {
+ UA_Chunk_delete(chunk);
+ return res;
}
- deleteChunks(&doneChunks);
- if(res != UA_STATUSCODE_GOOD)
- break;
+ /* Add to the decrypted-chunk queue */
+ SIMPLEQ_INSERT_TAIL(&channel->decryptedChunks, chunk, pointers);
- /* The channel is shutting down */
- if(channel->state == UA_SECURECHANNELSTATE_CLOSING)
- return UA_STATUSCODE_BADCONNECTIONCLOSED;
+ /* Check the resource limits */
+ channel->decryptedChunksCount++;
+ channel->decryptedChunksLength += chunk->bytes.length;
+ if((channel->config.localMaxChunkCount != 0 &&
+ channel->decryptedChunksCount > channel->config.localMaxChunkCount) ||
+ (channel->config.localMaxMessageSize != 0 &&
+ channel->decryptedChunksLength > channel->config.localMaxMessageSize)) {
+ return UA_STATUSCODE_BADTCPMESSAGETOOLARGE;
+ }
- /* Could we process a full message? Done? */
- UA_Chunk *next = SIMPLEQ_FIRST(&channel->completeChunks);
- if(chunk == next)
- break;
- chunk = next;
- }
+ /* Waiting for additional chunks */
+ if(chunk->chunkType == UA_CHUNKTYPE_INTERMEDIATE)
+ continue;
- /* Decrypt remaining MSG chunks. But abort before OPN. This allows us to
- * decrypt chunks while the rest of the message is still in transit,
- * resulting in speed improvements. */
+ /* Final chunk or abort. Reset the counters. */
+ channel->decryptedChunksCount = 0;
+ channel->decryptedChunksLength = 0;
- /* Channel configured? */
- const UA_SecurityPolicy *sp = channel->securityPolicy;
- if(!sp)
- return res;
-
- SIMPLEQ_FOREACH(chunk, &channel->completeChunks, pointers) {
- if(chunk->messageType != UA_MESSAGETYPE_MSG)
- break;
- if(chunk->decrypted)
+ /* Abort the message, remove all decrypted chunks
+ * TODO: Log a warning with the error code */
+ if(chunk->chunkType == UA_CHUNKTYPE_ABORT) {
+ while((chunk = SIMPLEQ_FIRST(&channel->decryptedChunks))) {
+ SIMPLEQ_REMOVE_HEAD(&channel->decryptedChunks, pointers);
+ UA_Chunk_delete(chunk);
+ }
continue;
- res = decryptAndVerifyChunk(channel, &sp->symmetricModule.cryptoModule,
- chunk->messageType, &chunk->bytes, 16);
- if(res != UA_STATUSCODE_GOOD)
- break;
- chunk->decrypted = true;
+ }
+
+ /* The decrypted queue contains a full message. Process it. */
+ UA_assert(chunk->chunkType == UA_CHUNKTYPE_FINAL);
+ res = assembleProcessMessage(channel, application, callback);
+ UA_CHECK_STATUS(res, return res);
}
- return res;
+
+ return UA_STATUSCODE_GOOD;
}
static UA_StatusCode
@@ -21087,21 +19413,25 @@ extractCompleteChunk(UA_SecureChannel *channel, const UA_ByteString *buffer,
/* At least 8 byte needed for the header. Wait for the next chunk. */
size_t initial_offset = *offset;
size_t remaining = buffer->length - initial_offset;
- if(remaining < 8) {
+ if(remaining < UA_SECURECHANNEL_MESSAGEHEADER_LENGTH) {
*done = true;
return UA_STATUSCODE_GOOD;
}
/* Decoding cannot fail */
UA_TcpMessageHeader hdr;
- UA_TcpMessageHeader_decodeBinary(buffer, &initial_offset, &hdr);
+ UA_StatusCode res =
+ UA_decodeBinaryInternal(buffer, &initial_offset, &hdr,
+ &UA_TRANSPORT[UA_TRANSPORT_TCPMESSAGEHEADER], NULL);
+ UA_assert(res == UA_STATUSCODE_GOOD);
+ (void)res; /* pacify compilers if assert is ignored */
UA_MessageType msgType = (UA_MessageType)
(hdr.messageTypeAndChunkType & UA_BITMASK_MESSAGETYPE);
UA_ChunkType chunkType = (UA_ChunkType)
(hdr.messageTypeAndChunkType & UA_BITMASK_CHUNKTYPE);
/* The message size is not allowed */
- if(hdr.messageSize < 16)
+ if(hdr.messageSize < UA_SECURECHANNEL_MESSAGE_MIN_LENGTH)
return UA_STATUSCODE_BADTCPMESSAGETYPEINVALID;
if(hdr.messageSize > channel->config.recvBufferSize)
return UA_STATUSCODE_BADTCPMESSAGETOOLARGE;
@@ -21117,38 +19447,33 @@ extractCompleteChunk(UA_SecureChannel *channel, const UA_ByteString *buffer,
chunkPayload.data = &buffer->data[*offset];
chunkPayload.length = hdr.messageSize;
- /* Connection-level messages. These are forwarded entirely. OPN message are
- * also forwarded undecrypted */
if(msgType == UA_MESSAGETYPE_HEL || msgType == UA_MESSAGETYPE_ACK ||
msgType == UA_MESSAGETYPE_ERR || msgType == UA_MESSAGETYPE_OPN) {
if(chunkType != UA_CHUNKTYPE_FINAL)
return UA_STATUSCODE_BADTCPMESSAGETYPEINVALID;
- goto add_chunk;
- }
-
- /* Only messages on SecureChannel-level with symmetric encryption afterwards */
- if(msgType != UA_MESSAGETYPE_MSG &&
- msgType != UA_MESSAGETYPE_CLO)
- return UA_STATUSCODE_BADTCPMESSAGETYPEINVALID;
+ } else {
+ /* Only messages on SecureChannel-level with symmetric encryption afterwards */
+ if(msgType != UA_MESSAGETYPE_MSG &&
+ msgType != UA_MESSAGETYPE_CLO)
+ return UA_STATUSCODE_BADTCPMESSAGETYPEINVALID;
- /* Check the chunk type before decrypting */
- if(chunkType != UA_CHUNKTYPE_FINAL &&
- chunkType != UA_CHUNKTYPE_INTERMEDIATE &&
- chunkType != UA_CHUNKTYPE_ABORT)
- return UA_STATUSCODE_BADTCPMESSAGETYPEINVALID;
+ /* Check the chunk type before decrypting */
+ if(chunkType != UA_CHUNKTYPE_FINAL &&
+ chunkType != UA_CHUNKTYPE_INTERMEDIATE &&
+ chunkType != UA_CHUNKTYPE_ABORT)
+ return UA_STATUSCODE_BADTCPMESSAGETYPEINVALID;
+ }
- add_chunk:
/* Add the chunk; forward the offset */
*offset += hdr.messageSize;
UA_Chunk *chunk = (UA_Chunk*)UA_malloc(sizeof(UA_Chunk));
- if(!chunk)
- return UA_STATUSCODE_BADOUTOFMEMORY;
+ UA_CHECK_MEM(chunk, return UA_STATUSCODE_BADOUTOFMEMORY);
+ chunk->bytes = chunkPayload;
chunk->messageType = msgType;
chunk->chunkType = chunkType;
- chunk->bytes = chunkPayload;
+ chunk->requestId = 0;
chunk->copied = false;
- chunk->decrypted = false;
SIMPLEQ_INSERT_TAIL(&channel->completeChunks, chunk, pointers);
return UA_STATUSCODE_GOOD;
@@ -21165,10 +19490,8 @@ UA_SecureChannel_processBuffer(UA_SecureChannel *channel, void *application,
if(appended.length > 0) {
channel->incompleteChunk = UA_BYTESTRING_NULL;
UA_Byte *t = (UA_Byte*)UA_realloc(appended.data, appended.length + buffer->length);
- if(!t) {
- UA_ByteString_deleteMembers(&appended);
- return UA_STATUSCODE_BADOUTOFMEMORY;
- }
+ UA_CHECK_MEM(t, UA_ByteString_clear(&appended);
+ return UA_STATUSCODE_BADOUTOFMEMORY);
memcpy(&t[appended.length], buffer->data, buffer->length);
appended.data = t;
appended.length += buffer->length;
@@ -21178,32 +19501,31 @@ UA_SecureChannel_processBuffer(UA_SecureChannel *channel, void *application,
/* Loop over the received chunks */
size_t offset = 0;
UA_Boolean done = false;
- UA_StatusCode res = UA_STATUSCODE_GOOD;
+ UA_StatusCode res;
while(!done) {
res = extractCompleteChunk(channel, buffer, &offset, &done);
- if(res != UA_STATUSCODE_GOOD)
- goto cleanup;
+ UA_CHECK_STATUS(res, goto cleanup);
}
/* Buffer half-received chunk. Before processing the messages so that
* processing is reentrant. */
if(offset < buffer->length) {
res = persistIncompleteChunk(channel, buffer, offset);
- if(res != UA_STATUSCODE_GOOD)
- goto cleanup;
+ UA_CHECK_STATUS(res, goto cleanup);
}
/* Process whatever we can. Chunks of completed and processed messages are
* removed. */
- res = processCompleteChunks(channel, application, callback);
- if(res != UA_STATUSCODE_GOOD)
- goto cleanup;
+ res = processChunks(channel, application, callback);
+ UA_CHECK_STATUS(res, goto cleanup);
- /* Persist full chunks that still point to the buffer */
- res = persistCompleteChunks(channel);
+ /* Persist full chunks that still point to the buffer. Can only return
+ * UA_STATUSCODE_BADOUTOFMEMORY as an error code. So merging res works. */
+ res |= persistCompleteChunks(&channel->completeChunks);
+ res |= persistCompleteChunks(&channel->decryptedChunks);
cleanup:
- UA_ByteString_deleteMembers(&appended);
+ UA_ByteString_clear(&appended);
return res;
}
@@ -21211,22 +19533,20 @@ UA_StatusCode
UA_SecureChannel_receive(UA_SecureChannel *channel, void *application,
UA_ProcessMessageCallback callback, UA_UInt32 timeout) {
UA_Connection *connection = channel->connection;
- if(!connection)
- return UA_STATUSCODE_BADINTERNALERROR;
+ UA_CHECK_MEM(connection, return UA_STATUSCODE_BADINTERNALERROR);
/* Listen for messages to arrive */
UA_ByteString buffer = UA_BYTESTRING_NULL;
- UA_StatusCode retval = connection->recv(connection, &buffer, timeout);
- if(retval != UA_STATUSCODE_GOOD)
- return retval;
+ UA_StatusCode res = connection->recv(connection, &buffer, timeout);
+ UA_CHECK_STATUS(res, return res);
/* Try to process one complete chunk */
- retval = UA_SecureChannel_processBuffer(channel, application, callback, &buffer);
+ res = UA_SecureChannel_processBuffer(channel, application, callback, &buffer);
connection->releaseRecvBuffer(connection, &buffer);
- return retval;
+ return res;
}
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/src/ua_securechannel_crypto.c" ***********************************/
+/**** amalgamated original file "/src/ua_securechannel_crypto.c" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -21243,39 +19563,28 @@ UA_SecureChannel_receive(UA_SecureChannel *channel, void *application,
-#define UA_ASYMMETRIC_ALG_SECURITY_HEADER_FIXED_LENGTH 12
-#define UA_SEQUENCE_HEADER_LENGTH 8
-#define UA_SYMMETRIC_ALG_SECURITY_HEADER_LENGTH 4
-#define UA_SECUREMH_AND_SYMALGH_LENGTH \
- (UA_SECURE_CONVERSATION_MESSAGE_HEADER_LENGTH + \
- UA_SYMMETRIC_ALG_SECURITY_HEADER_LENGTH)
-
UA_StatusCode
UA_SecureChannel_generateLocalNonce(UA_SecureChannel *channel) {
const UA_SecurityPolicy *sp = channel->securityPolicy;
- if(!sp)
- return UA_STATUSCODE_BADINTERNALERROR;
-
+ UA_CHECK_MEM(sp, return UA_STATUSCODE_BADINTERNALERROR);
UA_LOG_DEBUG_CHANNEL(sp->logger, channel, "Generating new local nonce");
/* Is the length of the previous nonce correct? */
size_t nonceLength = sp->symmetricModule.secureChannelNonceLength;
if(channel->localNonce.length != nonceLength) {
UA_ByteString_clear(&channel->localNonce);
- UA_StatusCode retval = UA_ByteString_allocBuffer(&channel->localNonce, nonceLength);
- if(retval != UA_STATUSCODE_GOOD)
- return retval;
+ UA_StatusCode res = UA_ByteString_allocBuffer(&channel->localNonce, nonceLength);
+ UA_CHECK_STATUS(res, return res);
}
- return sp->symmetricModule.generateNonce(sp, &channel->localNonce);
+ /* Generate the nonce */
+ return sp->symmetricModule.generateNonce(sp->policyContext, &channel->localNonce);
}
UA_StatusCode
UA_SecureChannel_generateLocalKeys(const UA_SecureChannel *channel) {
const UA_SecurityPolicy *sp = channel->securityPolicy;
- if(!sp)
- return UA_STATUSCODE_BADINTERNALERROR;
-
+ UA_CHECK_MEM(sp, return UA_STATUSCODE_BADINTERNALERROR);
UA_LOG_TRACE_CHANNEL(sp->logger, channel, "Generating new local keys");
void *cc = channel->channelContext;
@@ -21283,29 +19592,35 @@ UA_SecureChannel_generateLocalKeys(const UA_SecureChannel *channel) {
const UA_SecurityPolicySymmetricModule *sm = &sp->symmetricModule;
const UA_SecurityPolicyCryptoModule *crm = &sm->cryptoModule;
- /* Generate symmetric key buffer of the required length */
+ /* Generate symmetric key buffer of the required length. The block size is
+ * identical for local/remote. */
UA_ByteString buf;
- size_t encrKL = crm->encryptionAlgorithm.getLocalKeyLength(sp, cc);
- size_t encrBS = crm->encryptionAlgorithm.getLocalBlockSize(sp, cc);
- size_t signKL = crm->signatureAlgorithm.getLocalKeyLength(sp, cc);
+ size_t encrKL = crm->encryptionAlgorithm.getLocalKeyLength(cc);
+ size_t encrBS = crm->encryptionAlgorithm.getRemoteBlockSize(cc);
+ size_t signKL = crm->signatureAlgorithm.getLocalKeyLength(cc);
+ if(encrBS + signKL + encrKL == 0)
+ return UA_STATUSCODE_GOOD; /* No keys to generate */
+
UA_StatusCode retval = UA_ByteString_allocBuffer(&buf, encrBS + signKL + encrKL);
- if(retval != UA_STATUSCODE_GOOD)
- return retval;
+ UA_CHECK_STATUS(retval, return retval);
+ UA_ByteString localSigningKey = {signKL, buf.data};
+ UA_ByteString localEncryptingKey = {encrKL, &buf.data[signKL]};
+ UA_ByteString localIv = {encrBS, &buf.data[signKL + encrKL]};
/* Generate key */
- retval = sm->generateKey(sp, &channel->remoteNonce, &channel->localNonce, &buf);
- if(retval != UA_STATUSCODE_GOOD) {
- UA_ByteString_clear(&buf);
- return retval;
- }
+ retval = sm->generateKey(sp->policyContext, &channel->remoteNonce,
+ &channel->localNonce, &buf);
+ UA_CHECK_STATUS(retval, goto error);
/* Set the channel context */
- const UA_ByteString localSigningKey = {signKL, buf.data};
- const UA_ByteString localEncryptingKey = {encrKL, &buf.data[signKL]};
- const UA_ByteString localIv = {encrBS, &buf.data[signKL + encrKL]};
retval |= cm->setLocalSymSigningKey(cc, &localSigningKey);
retval |= cm->setLocalSymEncryptingKey(cc, &localEncryptingKey);
retval |= cm->setLocalSymIv(cc, &localIv);
+
+ error:
+ UA_CHECK_STATUS(retval, UA_LOG_WARNING_CHANNEL(sp->logger, channel,
+ "Could not generate local keys (statuscode: %s)",
+ UA_StatusCode_name(retval)));
UA_ByteString_clear(&buf);
return retval;
}
@@ -21313,9 +19628,7 @@ UA_SecureChannel_generateLocalKeys(const UA_SecureChannel *channel) {
UA_StatusCode
generateRemoteKeys(const UA_SecureChannel *channel) {
const UA_SecurityPolicy *sp = channel->securityPolicy;
- if(!sp)
- return UA_STATUSCODE_BADINTERNALERROR;
-
+ UA_CHECK_MEM(sp, return UA_STATUSCODE_BADINTERNALERROR);
UA_LOG_TRACE_CHANNEL(sp->logger, channel, "Generating new remote keys");
void *cc = channel->channelContext;
@@ -21325,27 +19638,32 @@ generateRemoteKeys(const UA_SecureChannel *channel) {
/* Generate symmetric key buffer of the required length */
UA_ByteString buf;
- size_t encrKL = crm->encryptionAlgorithm.getRemoteKeyLength(sp, cc);
- size_t encrBS = crm->encryptionAlgorithm.getRemoteBlockSize(sp, cc);
- size_t signKL = crm->signatureAlgorithm.getRemoteKeyLength(sp, cc);
+ size_t encrKL = crm->encryptionAlgorithm.getRemoteKeyLength(cc);
+ size_t encrBS = crm->encryptionAlgorithm.getRemoteBlockSize(cc);
+ size_t signKL = crm->signatureAlgorithm.getRemoteKeyLength(cc);
+ if(encrBS + signKL + encrKL == 0)
+ return UA_STATUSCODE_GOOD; /* No keys to generate */
+
UA_StatusCode retval = UA_ByteString_allocBuffer(&buf, encrBS + signKL + encrKL);
- if(retval != UA_STATUSCODE_GOOD) {
- UA_ByteString_clear(&buf);
- return retval;
- }
+ UA_CHECK_STATUS(retval, return retval);
+ UA_ByteString remoteSigningKey = {signKL, buf.data};
+ UA_ByteString remoteEncryptingKey = {encrKL, &buf.data[signKL]};
+ UA_ByteString remoteIv = {encrBS, &buf.data[signKL + encrKL]};
/* Generate key */
- retval = sm->generateKey(sp, &channel->localNonce, &channel->remoteNonce, &buf);
- if(retval != UA_STATUSCODE_GOOD)
- return retval;
+ retval = sm->generateKey(sp->policyContext, &channel->localNonce,
+ &channel->remoteNonce, &buf);
+ UA_CHECK_STATUS(retval, goto error);
/* Set the channel context */
- const UA_ByteString remoteSigningKey = {signKL, buf.data};
- const UA_ByteString remoteEncryptingKey = {encrKL, &buf.data[signKL]};
- const UA_ByteString remoteIv = {encrBS, &buf.data[signKL + encrKL]};
retval |= cm->setRemoteSymSigningKey(cc, &remoteSigningKey);
retval |= cm->setRemoteSymEncryptingKey(cc, &remoteEncryptingKey);
retval |= cm->setRemoteSymIv(cc, &remoteIv);
+
+ error:
+ UA_CHECK_STATUS(retval, UA_LOG_WARNING_CHANNEL(sp->logger, channel,
+ "Could not generate remote keys (statuscode: %s)",
+ UA_StatusCode_name(retval)));
UA_ByteString_clear(&buf);
return retval;
}
@@ -21354,16 +19672,17 @@ generateRemoteKeys(const UA_SecureChannel *channel) {
/* Send Asymmetric Message */
/***************************/
+/* The length of the static header content */
+#define UA_SECURECHANNEL_ASYMMETRIC_SECURITYHEADER_FIXED_LENGTH 12
+
size_t
calculateAsymAlgSecurityHeaderLength(const UA_SecureChannel *channel) {
const UA_SecurityPolicy *sp = channel->securityPolicy;
- if(!sp)
- return UA_STATUSCODE_BADINTERNALERROR;
+ UA_CHECK_MEM(sp, return UA_STATUSCODE_BADINTERNALERROR);
- size_t asymHeaderLength = UA_ASYMMETRIC_ALG_SECURITY_HEADER_FIXED_LENGTH +
+ size_t asymHeaderLength = UA_SECURECHANNEL_ASYMMETRIC_SECURITYHEADER_FIXED_LENGTH +
sp->policyUri.length;
- if(channel->securityMode != UA_MESSAGESECURITYMODE_SIGN &&
- channel->securityMode != UA_MESSAGESECURITYMODE_SIGNANDENCRYPT)
+ if(channel->securityMode == UA_MESSAGESECURITYMODE_NONE)
return asymHeaderLength;
/* OPN is always encrypted even if the mode is sign only */
@@ -21376,28 +19695,36 @@ UA_StatusCode
prependHeadersAsym(UA_SecureChannel *const channel, UA_Byte *header_pos,
const UA_Byte *buf_end, size_t totalLength,
size_t securityHeaderLength, UA_UInt32 requestId,
- size_t *const finalLength) {
+ size_t *const encryptedLength) {
const UA_SecurityPolicy *sp = channel->securityPolicy;
- if(!sp)
- return UA_STATUSCODE_BADINTERNALERROR;
+ UA_CHECK_MEM(sp, return UA_STATUSCODE_BADINTERNALERROR);
- size_t dataToEncryptLength =
- totalLength - (UA_SECURE_CONVERSATION_MESSAGE_HEADER_LENGTH + securityHeaderLength);
+ if(channel->securityMode == UA_MESSAGESECURITYMODE_NONE) {
+ *encryptedLength = totalLength;
+ } else {
+ size_t dataToEncryptLength = totalLength -
+ (UA_SECURECHANNEL_CHANNELHEADER_LENGTH + securityHeaderLength);
+ size_t plainTextBlockSize = sp->asymmetricModule.cryptoModule.
+ encryptionAlgorithm.getRemotePlainTextBlockSize(channel->channelContext);
+ size_t encryptedBlockSize = sp->asymmetricModule.cryptoModule.
+ encryptionAlgorithm.getRemoteBlockSize(channel->channelContext);
+
+ /* Padding always fills up the last block */
+ UA_assert(dataToEncryptLength % plainTextBlockSize == 0);
+ size_t blocks = dataToEncryptLength / plainTextBlockSize;
+ *encryptedLength = totalLength + blocks * (encryptedBlockSize - plainTextBlockSize);
+ }
UA_TcpMessageHeader messageHeader;
messageHeader.messageTypeAndChunkType = UA_MESSAGETYPE_OPN + UA_CHUNKTYPE_FINAL;
- messageHeader.messageSize = (UA_UInt32)
- (totalLength +
- UA_SecurityPolicy_getRemoteAsymEncryptionBufferLengthOverhead(sp, channel->channelContext,
- dataToEncryptLength));
+ messageHeader.messageSize = (UA_UInt32)*encryptedLength;
UA_UInt32 secureChannelId = channel->securityToken.channelId;
UA_StatusCode retval = UA_STATUSCODE_GOOD;
- retval |= UA_encodeBinary(&messageHeader, &UA_TRANSPORT[UA_TRANSPORT_TCPMESSAGEHEADER],
- &header_pos, &buf_end, NULL, NULL);
- retval |= UA_encodeBinary(&secureChannelId, &UA_TYPES[UA_TYPES_UINT32],
- &header_pos, &buf_end, NULL, NULL);
- if(retval != UA_STATUSCODE_GOOD)
- return retval;
+ retval |= UA_encodeBinaryInternal(&messageHeader,
+ &UA_TRANSPORT[UA_TRANSPORT_TCPMESSAGEHEADER],
+ &header_pos, &buf_end, NULL, NULL);
+ retval |= UA_UInt32_encodeBinary(&secureChannelId, &header_pos, buf_end);
+ UA_CHECK_STATUS(retval, return retval);
UA_AsymmetricAlgorithmSecurityHeader asymHeader;
UA_AsymmetricAlgorithmSecurityHeader_init(&asymHeader);
@@ -21408,94 +19735,91 @@ prependHeadersAsym(UA_SecureChannel *const channel, UA_Byte *header_pos,
asymHeader.receiverCertificateThumbprint.length = 20;
asymHeader.receiverCertificateThumbprint.data = channel->remoteCertificateThumbprint;
}
- retval = UA_encodeBinary(&asymHeader,
- &UA_TRANSPORT[UA_TRANSPORT_ASYMMETRICALGORITHMSECURITYHEADER],
- &header_pos, &buf_end, NULL, NULL);
- if(retval != UA_STATUSCODE_GOOD)
- return retval;
+ retval = UA_encodeBinaryInternal(&asymHeader,
+ &UA_TRANSPORT[UA_TRANSPORT_ASYMMETRICALGORITHMSECURITYHEADER],
+ &header_pos, &buf_end, NULL, NULL);
+ UA_CHECK_STATUS(retval, return retval);
UA_SequenceHeader seqHeader;
seqHeader.requestId = requestId;
seqHeader.sequenceNumber = UA_atomic_addUInt32(&channel->sendSequenceNumber, 1);
- retval = UA_encodeBinary(&seqHeader, &UA_TRANSPORT[UA_TRANSPORT_SEQUENCEHEADER],
- &header_pos, &buf_end, NULL, NULL);
-
- *finalLength = messageHeader.messageSize;
-
+ retval = UA_encodeBinaryInternal(&seqHeader, &UA_TRANSPORT[UA_TRANSPORT_SEQUENCEHEADER],
+ &header_pos, &buf_end, NULL, NULL);
return retval;
}
void
hideBytesAsym(const UA_SecureChannel *channel, UA_Byte **buf_start,
const UA_Byte **buf_end) {
- *buf_start += UA_SECURE_CONVERSATION_MESSAGE_HEADER_LENGTH;
+ /* Set buf_start to the beginning of the payload body */
+ *buf_start += UA_SECURECHANNEL_CHANNELHEADER_LENGTH;
*buf_start += calculateAsymAlgSecurityHeaderLength(channel);
- *buf_start += UA_SEQUENCE_HEADER_LENGTH;
+ *buf_start += UA_SECURECHANNEL_SEQUENCEHEADER_LENGTH;
#ifdef UA_ENABLE_ENCRYPTION
- if(channel->securityMode != UA_MESSAGESECURITYMODE_SIGN &&
- channel->securityMode != UA_MESSAGESECURITYMODE_SIGNANDENCRYPT)
+ if(channel->securityMode == UA_MESSAGESECURITYMODE_NONE)
return;
+ /* Make space for the certificate */
const UA_SecurityPolicy *sp = channel->securityPolicy;
-
- /* Hide bytes for signature and padding */
- size_t potentialEncryptMaxSize = (size_t)(*buf_end - *buf_start) + UA_SEQUENCE_HEADER_LENGTH;
*buf_end -= sp->asymmetricModule.cryptoModule.signatureAlgorithm.
- getLocalSignatureSize(sp, channel->channelContext);
- *buf_end -= 2; /* padding byte and extraPadding byte */
+ getLocalSignatureSize(channel->channelContext);
- /* Add some overhead length due to RSA implementations adding a signature themselves */
- *buf_end -= UA_SecurityPolicy_getRemoteAsymEncryptionBufferLengthOverhead(sp,
- channel->channelContext,
- potentialEncryptMaxSize);
+ /* Block sizes depend on the remote key (certificate) */
+ size_t plainTextBlockSize = sp->asymmetricModule.cryptoModule.
+ encryptionAlgorithm.getRemotePlainTextBlockSize(channel->channelContext);
+ size_t encryptedBlockSize = sp->asymmetricModule.cryptoModule.
+ encryptionAlgorithm.getRemoteBlockSize(channel->channelContext);
+ UA_Boolean extraPadding = (sp->asymmetricModule.cryptoModule.encryptionAlgorithm.
+ getRemoteKeyLength(channel->channelContext) > 2048);
+
+ /* Compute the maximum number of encrypted blocks that can fit entirely
+ * before the signature. From that compute the maximum usable plaintext
+ * size. */
+ size_t maxEncrypted = (size_t)(*buf_end - *buf_start) +
+ UA_SECURECHANNEL_SEQUENCEHEADER_LENGTH;
+ size_t max_blocks = maxEncrypted / encryptedBlockSize;
+ size_t paddingBytes = (UA_LIKELY(!extraPadding)) ? 1u : 2u;
+ *buf_end = *buf_start + (max_blocks * plainTextBlockSize) -
+ UA_SECURECHANNEL_SEQUENCEHEADER_LENGTH - paddingBytes;
#endif
}
#ifdef UA_ENABLE_ENCRYPTION
+/* Assumes that pos can be advanced to the end of the current block */
void
-padChunkAsym(UA_SecureChannel *channel, const UA_ByteString *buf,
- size_t securityHeaderLength, UA_Byte **buf_pos) {
- const UA_SecurityPolicy *sp = channel->securityPolicy;
+padChunk(UA_SecureChannel *channel, const UA_SecurityPolicyCryptoModule *cm,
+ const UA_Byte *start, UA_Byte **pos) {
+ const size_t bytesToWrite = (uintptr_t)*pos - (uintptr_t)start;
+ size_t signatureSize = cm->signatureAlgorithm.
+ getLocalSignatureSize(channel->channelContext);
+ size_t plainTextBlockSize = cm->encryptionAlgorithm.
+ getRemotePlainTextBlockSize(channel->channelContext);
+ UA_Boolean extraPadding = (cm->encryptionAlgorithm.
+ getRemoteKeyLength(channel->channelContext) > 2048);
+ size_t paddingBytes = (UA_LIKELY(!extraPadding)) ? 1u : 2u;
+
+ size_t lastBlock = ((bytesToWrite + signatureSize + paddingBytes) % plainTextBlockSize);
+ size_t paddingLength = (lastBlock != 0) ? plainTextBlockSize - lastBlock : 0;
- /* Also pad if the securityMode is SIGN_ONLY, since we are using
- * asymmetric communication to exchange keys and thus need to encrypt. */
- if(channel->securityMode != UA_MESSAGESECURITYMODE_SIGN &&
- channel->securityMode != UA_MESSAGESECURITYMODE_SIGNANDENCRYPT)
- return;
+ UA_LOG_TRACE_CHANNEL(channel->securityPolicy->logger, channel,
+ "Add %lu bytes of padding plus %lu padding size bytes",
+ (long unsigned int)paddingLength,
+ (long unsigned int)paddingBytes);
- const UA_Byte *buf_body_start =
- &buf->data[UA_SECURE_CONVERSATION_MESSAGE_HEADER_LENGTH +
- UA_SEQUENCE_HEADER_LENGTH + securityHeaderLength];
- const size_t bytesToWrite =
- (uintptr_t)*buf_pos - (uintptr_t)buf_body_start + UA_SEQUENCE_HEADER_LENGTH;
-
- /* Compute the padding length */
- size_t plainTextBlockSize = sp->asymmetricModule.cryptoModule.encryptionAlgorithm.
- getRemotePlainTextBlockSize(sp, channel->channelContext);
- size_t signatureSize = sp->asymmetricModule.cryptoModule.signatureAlgorithm.
- getLocalSignatureSize(sp, channel->channelContext);
- size_t paddingBytes = 1;
- if(sp->asymmetricModule.cryptoModule.encryptionAlgorithm.
- getRemoteKeyLength(sp, channel->channelContext) > 2048)
- ++paddingBytes; /* extra padding */
- size_t totalPaddingSize =
- (plainTextBlockSize - ((bytesToWrite + signatureSize + paddingBytes) % plainTextBlockSize));
-
- /* Write the padding. This is <= because the paddingSize byte also has to be written */
- UA_Byte paddingSize = (UA_Byte)(totalPaddingSize & 0xffu);
- for(UA_UInt16 i = 0; i <= totalPaddingSize; ++i) {
- **buf_pos = paddingSize;
- ++*buf_pos;
+ /* Write the padding. This is <= because the paddingSize byte also has to be
+ * written */
+ UA_Byte paddingByte = (UA_Byte)paddingLength;
+ for(UA_UInt16 i = 0; i <= paddingLength; ++i) {
+ **pos = paddingByte;
+ ++*pos;
}
/* Write the extra padding byte if required */
- if(sp->asymmetricModule.cryptoModule.encryptionAlgorithm.
- getRemoteKeyLength(sp, channel->channelContext) > 2048) {
- UA_Byte extraPaddingSize = (UA_Byte)(totalPaddingSize >> 8u);
- **buf_pos = extraPaddingSize;
- ++*buf_pos;
+ if(extraPadding) {
+ **pos = (UA_Byte)(paddingLength >> 8u);
+ ++*pos;
}
}
@@ -21507,154 +19831,110 @@ signAndEncryptAsym(UA_SecureChannel *channel, size_t preSignLength,
channel->securityMode != UA_MESSAGESECURITYMODE_SIGNANDENCRYPT)
return UA_STATUSCODE_GOOD;
- const UA_SecurityPolicy *sp = channel->securityPolicy;
-
/* Sign message */
+ const UA_SecurityPolicy *sp = channel->securityPolicy;
const UA_ByteString dataToSign = {preSignLength, buf->data};
size_t sigsize = sp->asymmetricModule.cryptoModule.signatureAlgorithm.
- getLocalSignatureSize(sp, channel->channelContext);
+ getLocalSignatureSize(channel->channelContext);
UA_ByteString signature = {sigsize, buf->data + preSignLength};
UA_StatusCode retval = sp->asymmetricModule.cryptoModule.signatureAlgorithm.
- sign(sp, channel->channelContext, &dataToSign, &signature);
- if(retval != UA_STATUSCODE_GOOD)
- return retval;
+ sign(channel->channelContext, &dataToSign, &signature);
+ UA_CHECK_STATUS(retval, return retval);
/* Specification part 6, 6.7.4: The OpenSecureChannel Messages are
* signed and encrypted if the SecurityMode is not None (even if the
* SecurityMode is SignOnly). */
size_t unencrypted_length =
- UA_SECURE_CONVERSATION_MESSAGE_HEADER_LENGTH + securityHeaderLength;
+ UA_SECURECHANNEL_CHANNELHEADER_LENGTH + securityHeaderLength;
UA_ByteString dataToEncrypt = {totalLength - unencrypted_length,
&buf->data[unencrypted_length]};
return sp->asymmetricModule.cryptoModule.encryptionAlgorithm.
- encrypt(sp, channel->channelContext, &dataToEncrypt);
+ encrypt(channel->channelContext, &dataToEncrypt);
}
/**************************/
/* Send Symmetric Message */
/**************************/
-static UA_UInt16
-calculatePaddingSym(const UA_SecurityPolicy *sp, const void *channelContext,
- size_t bytesToWrite, UA_Byte *paddingSize, UA_Byte *extraPaddingSize) {
- size_t encryptionBlockSize = sp->symmetricModule.cryptoModule.
- encryptionAlgorithm.getLocalBlockSize(sp, channelContext);
- size_t signatureSize = sp->symmetricModule.cryptoModule.signatureAlgorithm.
- getLocalSignatureSize(sp, channelContext);
-
- size_t padding = (encryptionBlockSize -
- ((bytesToWrite + signatureSize + 1) % encryptionBlockSize));
- *paddingSize = (UA_Byte)padding;
- *extraPaddingSize = (UA_Byte)(padding >> 8u);
- return (UA_UInt16)padding;
-}
-
-void
-padChunkSym(UA_MessageContext *messageContext, size_t bodyLength) {
- if(messageContext->channel->securityMode != UA_MESSAGESECURITYMODE_SIGNANDENCRYPT)
- return;
-
- /* The bytes for the padding and signature were removed from buf_end before
- * encoding the payload. So we don't have to check if there is enough
- * space. */
-
- size_t bytesToWrite = bodyLength + UA_SEQUENCE_HEADER_LENGTH;
- UA_Byte paddingSize = 0;
- UA_Byte extraPaddingSize = 0;
- UA_UInt16 totalPaddingSize =
- calculatePaddingSym(messageContext->channel->securityPolicy,
- messageContext->channel->channelContext,
- bytesToWrite, &paddingSize, &extraPaddingSize);
-
- /* This is <= because the paddingSize byte also has to be written. */
- for(UA_UInt16 i = 0; i <= totalPaddingSize; ++i) {
- *messageContext->buf_pos = paddingSize;
- ++(messageContext->buf_pos);
- }
- if(extraPaddingSize > 0) {
- *messageContext->buf_pos = extraPaddingSize;
- ++(messageContext->buf_pos);
- }
-}
-
UA_StatusCode
-signChunkSym(UA_MessageContext *const messageContext, size_t preSigLength) {
+signAndEncryptSym(UA_MessageContext *messageContext,
+ size_t preSigLength, size_t totalLength) {
const UA_SecureChannel *channel = messageContext->channel;
- if(channel->securityMode != UA_MESSAGESECURITYMODE_SIGN &&
- channel->securityMode != UA_MESSAGESECURITYMODE_SIGNANDENCRYPT)
+ if(channel->securityMode == UA_MESSAGESECURITYMODE_NONE)
return UA_STATUSCODE_GOOD;
+ /* Sign */
const UA_SecurityPolicy *sp = channel->securityPolicy;
UA_ByteString dataToSign = messageContext->messageBuffer;
dataToSign.length = preSigLength;
UA_ByteString signature;
signature.length = sp->symmetricModule.cryptoModule.signatureAlgorithm.
- getLocalSignatureSize(sp, channel->channelContext);
+ getLocalSignatureSize(channel->channelContext);
signature.data = messageContext->buf_pos;
+ UA_StatusCode res = sp->symmetricModule.cryptoModule.signatureAlgorithm.
+ sign(channel->channelContext, &dataToSign, &signature);
+ UA_CHECK_STATUS(res, return res);
- return sp->symmetricModule.cryptoModule.signatureAlgorithm.
- sign(sp, channel->channelContext, &dataToSign, &signature);
-}
-
-UA_StatusCode
-encryptChunkSym(UA_MessageContext *const messageContext, size_t totalLength) {
- const UA_SecureChannel *channel = messageContext->channel;
if(channel->securityMode != UA_MESSAGESECURITYMODE_SIGNANDENCRYPT)
return UA_STATUSCODE_GOOD;
-
- UA_ByteString dataToEncrypt;
- dataToEncrypt.data = messageContext->messageBuffer.data + UA_SECUREMH_AND_SYMALGH_LENGTH;
- dataToEncrypt.length = totalLength - UA_SECUREMH_AND_SYMALGH_LENGTH;
- const UA_SecurityPolicy *sp = channel->securityPolicy;
+ /* Encrypt */
+ UA_ByteString dataToEncrypt;
+ dataToEncrypt.data = messageContext->messageBuffer.data +
+ UA_SECURECHANNEL_CHANNELHEADER_LENGTH +
+ UA_SECURECHANNEL_SYMMETRIC_SECURITYHEADER_LENGTH;
+ dataToEncrypt.length = totalLength -
+ (UA_SECURECHANNEL_CHANNELHEADER_LENGTH +
+ UA_SECURECHANNEL_SYMMETRIC_SECURITYHEADER_LENGTH);
return sp->symmetricModule.cryptoModule.encryptionAlgorithm.
- encrypt(sp, channel->channelContext, &dataToEncrypt);
+ encrypt(channel->channelContext, &dataToEncrypt);
}
#endif /* UA_ENABLE_ENCRYPTION */
void
setBufPos(UA_MessageContext *mc) {
- /* Forward the data pointer so that the payload is encoded after the
- * message header */
- mc->buf_pos = &mc->messageBuffer.data[UA_SECURE_MESSAGE_HEADER_LENGTH];
+ /* Forward the data pointer so that the payload is encoded after the message
+ * header. This has to be a symmetric message because OPN (with asymmetric
+ * encryption) does not support chunking. */
+ mc->buf_pos = &mc->messageBuffer.data[UA_SECURECHANNEL_SYMMETRIC_HEADER_TOTALLENGTH];
mc->buf_end = &mc->messageBuffer.data[mc->messageBuffer.length];
#ifdef UA_ENABLE_ENCRYPTION
+ if(mc->channel->securityMode == UA_MESSAGESECURITYMODE_NONE)
+ return;
+
const UA_SecureChannel *channel = mc->channel;
const UA_SecurityPolicy *sp = channel->securityPolicy;
+ size_t sigsize = sp->symmetricModule.cryptoModule.signatureAlgorithm.
+ getLocalSignatureSize(channel->channelContext);
+ size_t plainBlockSize = sp->symmetricModule.cryptoModule.
+ encryptionAlgorithm.getRemotePlainTextBlockSize(channel->channelContext);
+
+ /* Assuming that for symmetric encryption the plainTextBlockSize ==
+ * cypherTextBlockSize. For symmetric encryption the remote/local block
+ * sizes are identical. */
+ UA_assert(sp->symmetricModule.cryptoModule.encryptionAlgorithm.
+ getRemoteBlockSize(channel->channelContext) == plainBlockSize);
+
+ /* Leave enough space for the signature and padding */
+ mc->buf_end -= sigsize;
+ mc->buf_end -= mc->messageBuffer.length % plainBlockSize;
- /* Reserve space for the message footer at the end of the chunk if the chunk
- * is signed and/or encrypted. The footer includes the fields PaddingSize,
- * Padding, ExtraPadding and Signature. The padding fields are only present
- * if the chunk is encrypted. */
- if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGN ||
- channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT)
- mc->buf_end -= sp->symmetricModule.cryptoModule.signatureAlgorithm.
- getLocalSignatureSize(sp, channel->channelContext);
-
- /* The size of the padding depends on the amount of data that shall be sent
- * and is unknown at this point. Reserve space for the PaddingSize byte,
- * the maximum amount of Padding which equals the block size of the
- * symmetric encryption algorithm and last 1 byte for the ExtraPaddingSize
- * field that is present if the encryption key is larger than 2048 bits.
- * The actual padding size is later calculated by the function
- * calculatePaddingSym(). */
if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) {
- /* PaddingSize and ExtraPaddingSize fields */
- size_t encryptionBlockSize = sp->symmetricModule.cryptoModule.
- encryptionAlgorithm.getLocalBlockSize(sp, channel->channelContext);
- mc->buf_end -= 1 + ((encryptionBlockSize >> 8u) ? 1 : 0);
-
- /* Reduce the message body size with the remainder of the operation
- * maxEncryptedDataSize modulo EncryptionBlockSize to get a whole
- * number of blocks to encrypt later. Also reserve one byte for
- * padding (1 <= paddingSize <= encryptionBlockSize). */
- size_t maxEncryptDataSize = mc->messageBuffer.length -
- UA_SECURE_CONVERSATION_MESSAGE_HEADER_LENGTH -
- UA_SYMMETRIC_ALG_SECURITY_HEADER_LENGTH;
- mc->buf_end -= (maxEncryptDataSize % encryptionBlockSize) + 1;
- }
+ /* Reserve space for the padding bytes */
+ UA_Boolean extraPadding =
+ (sp->symmetricModule.cryptoModule.encryptionAlgorithm.
+ getRemoteKeyLength(channel->channelContext) > 2048);
+ mc->buf_end -= (UA_LIKELY(!extraPadding)) ? 1 : 2;
+ }
+
+ UA_LOG_TRACE_CHANNEL(sp->logger, channel,
+ "Prepare a symmetric message buffer of length %lu "
+ "with a usable maximum payload length of %lu",
+ (long unsigned)mc->messageBuffer.length,
+ (long unsigned)((uintptr_t)mc->buf_end -
+ (uintptr_t)mc->messageBuffer.data));
#endif
}
@@ -21662,36 +19942,23 @@ setBufPos(UA_MessageContext *mc) {
/* Process a received Chunk */
/****************************/
-static UA_UInt16
-decodeChunkPadding(const UA_SecureChannel *channel,
- const UA_SecurityPolicyCryptoModule *cryptoModule,
- UA_MessageType messageType, const UA_ByteString *chunk,
- size_t sigsize) {
- /* Is padding used? */
- if(channel->securityMode != UA_MESSAGESECURITYMODE_SIGNANDENCRYPT &&
- !(messageType == UA_MESSAGETYPE_OPN &&
- !UA_String_equal(&cryptoModule->encryptionAlgorithm.uri, &UA_STRING_NULL)))
- return 0;
-
+static size_t
+decodePadding(const UA_SecureChannel *channel,
+ const UA_SecurityPolicyCryptoModule *cryptoModule,
+ const UA_ByteString *chunk, size_t sigsize) {
+ /* Read the byte with the padding size */
size_t paddingSize = chunk->data[chunk->length - sigsize - 1];
/* Extra padding size */
- size_t keyLength = cryptoModule->encryptionAlgorithm.
- getLocalKeyLength(channel->securityPolicy, channel->channelContext);
- if(keyLength > 2048) {
+ if(cryptoModule->encryptionAlgorithm.
+ getLocalKeyLength(channel->channelContext) > 2048) {
paddingSize <<= 8u;
- paddingSize += 1;
paddingSize += chunk->data[chunk->length - sigsize - 2];
+ paddingSize += 1; /* Extra padding byte itself */
}
- /* We need to add one to the padding size since the paddingSize byte itself
- * need to be removed as well. */
- paddingSize += 1;
-
- UA_LOG_TRACE_CHANNEL(channel->securityPolicy->logger, channel,
- "Calculated padding size to be %lu",
- (long unsigned int)paddingSize);
- return (UA_UInt16)paddingSize;
+ /* Add one since the paddingSize byte itself needs to be removed as well */
+ return paddingSize + 1;
}
static UA_StatusCode
@@ -21700,12 +19967,11 @@ verifySignature(const UA_SecureChannel *channel,
const UA_ByteString *chunk, size_t sigsize) {
UA_LOG_TRACE_CHANNEL(channel->securityPolicy->logger, channel,
"Verifying chunk signature");
- if(sigsize >= chunk->length)
- return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
+ UA_CHECK(sigsize < chunk->length, return UA_STATUSCODE_BADSECURITYCHECKSFAILED);
const UA_ByteString content = {chunk->length - sigsize, chunk->data};
const UA_ByteString sig = {sigsize, chunk->data + chunk->length - sigsize};
UA_StatusCode retval = cryptoModule->signatureAlgorithm.
- verify(channel->securityPolicy, channel->channelContext, &content, &sig);
+ verify(channel->channelContext, &content, &sig);
#ifdef UA_ENABLE_UNIT_TEST_FAILURE_HOOKS
retval |= decrypt_verifySignatureFailure;
#endif
@@ -21721,15 +19987,12 @@ decryptAndVerifyChunk(const UA_SecureChannel *channel,
size_t offset) {
/* Decrypt the chunk */
UA_StatusCode res = UA_STATUSCODE_GOOD;
- const UA_SecurityPolicy *sp = channel->securityPolicy;
if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT ||
messageType == UA_MESSAGETYPE_OPN) {
- UA_ByteString cipherText = {chunk->length - offset, chunk->data + offset};
- res = cryptoModule->encryptionAlgorithm.
- decrypt(sp, channel->channelContext, &cipherText);
- if(res != UA_STATUSCODE_GOOD)
- return res;
- chunk->length = cipherText.length + offset;
+ UA_ByteString cipher = {chunk->length - offset, chunk->data + offset};
+ res = cryptoModule->encryptionAlgorithm.decrypt(channel->channelContext, &cipher);
+ UA_CHECK_STATUS(res, return res);
+ chunk->length = cipher.length + offset;
}
/* Does the message have a signature? */
@@ -21740,27 +20003,33 @@ decryptAndVerifyChunk(const UA_SecureChannel *channel,
/* Verify the chunk signature */
size_t sigsize = cryptoModule->signatureAlgorithm.
- getRemoteSignatureSize(sp, channel->channelContext);
+ getRemoteSignatureSize(channel->channelContext);
res = verifySignature(channel, cryptoModule, chunk, sigsize);
- if(res != UA_STATUSCODE_GOOD)
- return res;
+ UA_CHECK_STATUS(res,
+ UA_LOG_WARNING_CHANNEL(channel->securityPolicy->logger, channel,
+ "Could not verify the signature"); return res);
- /* Compute and verify the padding. The encrypted payload has to be at least
- * 9 bytes long (8 byte for the SequenceHeader and one byte for the actual
- * message). */
- size_t paddingSize =
- decodeChunkPadding(channel, cryptoModule, messageType, chunk, sigsize);
- if(offset + paddingSize + sigsize + 9 >= chunk->length)
- return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
+ /* Compute the padding if the payload as encrypted */
+ size_t padSize = 0;
+ if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT ||
+ (messageType == UA_MESSAGETYPE_OPN &&
+ cryptoModule->encryptionAlgorithm.uri.length > 0)) {
+ padSize = decodePadding(channel, cryptoModule, chunk, sigsize);
+ UA_LOG_TRACE_CHANNEL(channel->securityPolicy->logger, channel,
+ "Calculated padding size to be %lu",
+ (long unsigned)padSize);
+ }
+
+ /* Verify the content length. The encrypted payload has to be at least 9
+ * bytes long: 8 byte for the SequenceHeader and one byte for the actual
+ * message */
+ UA_CHECK(offset + padSize + sigsize + 9 < chunk->length,
+ UA_LOG_WARNING_CHANNEL(channel->securityPolicy->logger, channel,
+ "Impossible padding value");
+ return UA_STATUSCODE_BADSECURITYCHECKSFAILED);
/* Hide the signature and padding */
- chunk->length -= (sigsize + paddingSize);
- return UA_STATUSCODE_GOOD;
-}
-
-UA_StatusCode
-processSequenceNumberAsym(UA_SecureChannel *channel, UA_UInt32 sequenceNumber) {
- channel->receiveSequenceNumber = sequenceNumber;
+ chunk->length -= (sigsize + padSize);
return UA_STATUSCODE_GOOD;
}
@@ -21768,7 +20037,6 @@ UA_StatusCode
checkAsymHeader(UA_SecureChannel *channel,
const UA_AsymmetricAlgorithmSecurityHeader *asymHeader) {
const UA_SecurityPolicy *sp = channel->securityPolicy;
-
if(!UA_ByteString_equal(&sp->policyUri, &asymHeader->securityPolicyUri))
return UA_STATUSCODE_BADSECURITYPOLICYREJECTED;
@@ -21781,7 +20049,7 @@ checkAsymHeader(UA_SecureChannel *channel,
}
UA_StatusCode
-checkSymHeader(UA_SecureChannel *channel, UA_UInt32 tokenId) {
+checkSymHeader(UA_SecureChannel *channel, const UA_UInt32 tokenId) {
/* If no match, try to revolve to the next token after a
* RenewSecureChannel */
UA_StatusCode retval = UA_STATUSCODE_GOOD;
@@ -21798,18 +20066,18 @@ checkSymHeader(UA_SecureChannel *channel, UA_UInt32 tokenId) {
break;
/* Not the new token */
- if(tokenId != channel->altSecurityToken.tokenId) {
- UA_LOG_WARNING_CHANNEL(channel->securityPolicy->logger, channel,
- "Unknown SecurityToken");
- return UA_STATUSCODE_BADSECURECHANNELTOKENUNKNOWN;
- }
+ UA_CHECK(tokenId == channel->altSecurityToken.tokenId,
+ UA_LOG_WARNING_CHANNEL(channel->securityPolicy->logger, channel,
+ "Unknown SecurityToken");
+ return UA_STATUSCODE_BADSECURECHANNELTOKENUNKNOWN);
/* Roll over to the new token, generate new local and remote keys */
channel->renewState = UA_SECURECHANNELRENEWSTATE_NORMAL;
channel->securityToken = channel->altSecurityToken;
UA_ChannelSecurityToken_init(&channel->altSecurityToken);
- retval = UA_SecureChannel_generateLocalKeys(channel);
+ retval |= UA_SecureChannel_generateLocalKeys(channel);
retval |= generateRemoteKeys(channel);
+ UA_CHECK_STATUS(retval, return retval);
break;
case UA_SECURECHANNELRENEWSTATE_NEWTOKEN_CLIENT:
@@ -21820,11 +20088,10 @@ checkSymHeader(UA_SecureChannel *channel, UA_UInt32 tokenId) {
}
/* Not the new token */
- if(tokenId != channel->securityToken.tokenId) {
- UA_LOG_WARNING_CHANNEL(channel->securityPolicy->logger, channel,
- "Unknown SecurityToken");
- return UA_STATUSCODE_BADSECURECHANNELTOKENUNKNOWN;
- }
+ UA_CHECK(tokenId == channel->securityToken.tokenId,
+ UA_LOG_WARNING_CHANNEL(channel->securityPolicy->logger, channel,
+ "Unknown SecurityToken");
+ return UA_STATUSCODE_BADSECURECHANNELTOKENUNKNOWN);
/* The remote server uses the new token for the first time. Delete the
* old token and roll the remote key over. The local key already uses
@@ -21832,11 +20099,9 @@ checkSymHeader(UA_SecureChannel *channel, UA_UInt32 tokenId) {
channel->renewState = UA_SECURECHANNELRENEWSTATE_NORMAL;
UA_ChannelSecurityToken_init(&channel->altSecurityToken);
retval = generateRemoteKeys(channel);
+ UA_CHECK_STATUS(retval, return retval);
}
- if(retval != UA_STATUSCODE_GOOD)
- return retval;
-
UA_DateTime timeout = token->createdAt + (token->revisedLifetime * UA_DATETIME_MSEC);
if(channel->state == UA_SECURECHANNELSTATE_OPEN &&
timeout < UA_DateTime_nowMonotonic()) {
@@ -21849,27 +20114,7 @@ checkSymHeader(UA_SecureChannel *channel, UA_UInt32 tokenId) {
return UA_STATUSCODE_GOOD;
}
-/* Functionality used by both the SecureChannel and the SecurityPolicy */
-
-size_t
-UA_SecurityPolicy_getRemoteAsymEncryptionBufferLengthOverhead(const UA_SecurityPolicy *securityPolicy,
- const void *channelContext,
- size_t maxEncryptionLength) {
- if(maxEncryptionLength == 0)
- return 0;
-
- size_t plainTextBlockSize = securityPolicy->asymmetricModule.cryptoModule.
- encryptionAlgorithm.getRemotePlainTextBlockSize(securityPolicy, channelContext);
- size_t encryptedBlockSize = securityPolicy->asymmetricModule.cryptoModule.
- encryptionAlgorithm.getRemoteBlockSize(securityPolicy, channelContext);
- if(plainTextBlockSize == 0)
- return 0;
-
- size_t maxNumberOfBlocks = maxEncryptionLength / plainTextBlockSize;
- return maxNumberOfBlocks * (encryptedBlockSize - plainTextBlockSize);
-}
-
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/src/server/ua_session.c" ***********************************/
+/**** amalgamated original file "/src/server/ua_session.c" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -21890,17 +20135,32 @@ void UA_Session_init(UA_Session *session) {
session->availableContinuationPoints = UA_MAXCONTINUATIONPOINTS;
#ifdef UA_ENABLE_SUBSCRIPTIONS
SIMPLEQ_INIT(&session->responseQueue);
+ TAILQ_INIT(&session->subscriptions);
#endif
}
-void UA_Session_deleteMembersCleanup(UA_Session *session, UA_Server* server) {
- UA_LOCK_ASSERT(server->serviceMutex, 1);
+void UA_Session_clear(UA_Session *session, UA_Server* server) {
+ UA_LOCK_ASSERT(&server->serviceMutex, 1);
+
+ /* Remove all Subscriptions. This may send out remaining publish
+ * responses. */
+#ifdef UA_ENABLE_SUBSCRIPTIONS
+ UA_Subscription *sub, *tempsub;
+ TAILQ_FOREACH_SAFE(sub, &session->subscriptions, sessionListEntry, tempsub) {
+ UA_Subscription_delete(server, sub);
+ }
+#endif
+
+#ifdef UA_ENABLE_DIAGNOSTICS
+ deleteNode(server, session->sessionId, true);
+#endif
+
UA_Session_detachFromSecureChannel(session);
- UA_ApplicationDescription_deleteMembers(&session->clientDescription);
- UA_NodeId_deleteMembers(&session->header.authenticationToken);
- UA_NodeId_deleteMembers(&session->sessionId);
- UA_String_deleteMembers(&session->sessionName);
- UA_ByteString_deleteMembers(&session->serverNonce);
+ UA_ApplicationDescription_clear(&session->clientDescription);
+ UA_NodeId_clear(&session->header.authenticationToken);
+ UA_NodeId_clear(&session->sessionId);
+ UA_String_clear(&session->sessionName);
+ UA_ByteString_clear(&session->serverNonce);
struct ContinuationPoint *cp, *next = session->continuationPoints;
while((cp = next)) {
next = ContinuationPoint_clear(cp);
@@ -21908,12 +20168,28 @@ void UA_Session_deleteMembersCleanup(UA_Session *session, UA_Server* server) {
}
session->continuationPoints = NULL;
session->availableContinuationPoints = UA_MAXCONTINUATIONPOINTS;
+
+ UA_Array_delete(session->params, session->paramsSize,
+ &UA_TYPES[UA_TYPES_KEYVALUEPAIR]);
+ session->params = NULL;
+ session->paramsSize = 0;
+
+ UA_Array_delete(session->localeIds, session->localeIdsSize,
+ &UA_TYPES[UA_TYPES_STRING]);
+ session->localeIds = NULL;
+ session->localeIdsSize = 0;
+
+#ifdef UA_ENABLE_DIAGNOSTICS
+ UA_SessionDiagnosticsDataType_clear(&session->diagnostics);
+ UA_SessionSecurityDiagnosticsDataType_clear(&session->securityDiagnostics);
+#endif
}
void
UA_Session_attachToSecureChannel(UA_Session *session, UA_SecureChannel *channel) {
UA_Session_detachFromSecureChannel(session);
session->header.channel = channel;
+ session->header.serverSession = true;
SLIST_INSERT_HEAD(&channel->sessions, &session->header, next);
}
@@ -21930,6 +20206,16 @@ UA_Session_detachFromSecureChannel(UA_Session *session) {
SLIST_REMOVE(&channel->sessions, sh, UA_SessionHeader, next);
break;
}
+
+ /* Clean up the response queue. Their RequestId is bound to the
+ * SecureChannel so they cannot be reused. */
+#ifdef UA_ENABLE_SUBSCRIPTIONS
+ UA_PublishResponseEntry *pre;
+ while((pre = UA_Session_dequeuePublishReq(session))) {
+ UA_PublishResponse_clear(&pre->response);
+ UA_free(pre);
+ }
+#endif
}
UA_StatusCode
@@ -21940,7 +20226,7 @@ UA_Session_generateNonce(UA_Session *session) {
/* Is the length of the previous nonce correct? */
if(session->serverNonce.length != UA_SESSION_NONCELENTH) {
- UA_ByteString_deleteMembers(&session->serverNonce);
+ UA_ByteString_clear(&session->serverNonce);
UA_StatusCode retval =
UA_ByteString_allocBuffer(&session->serverNonce, UA_SESSION_NONCELENTH);
if(retval != UA_STATUSCODE_GOOD)
@@ -21948,54 +20234,91 @@ UA_Session_generateNonce(UA_Session *session) {
}
return channel->securityPolicy->symmetricModule.
- generateNonce(channel->securityPolicy, &session->serverNonce);
+ generateNonce(channel->securityPolicy->policyContext, &session->serverNonce);
}
void UA_Session_updateLifetime(UA_Session *session) {
session->validTill = UA_DateTime_nowMonotonic() +
(UA_DateTime)(session->timeout * UA_DATETIME_MSEC);
+#ifdef UA_ENABLE_DIAGNOSTICS
+ session->diagnostics.clientLastContactTime = UA_DateTime_now();
+#endif
}
#ifdef UA_ENABLE_SUBSCRIPTIONS
-void UA_Session_addSubscription(UA_Server *server, UA_Session *session, UA_Subscription *newSubscription) {
- newSubscription->subscriptionId = ++session->lastSubscriptionId;
-
- LIST_INSERT_HEAD(&session->serverSubscriptions, newSubscription, listEntry);
- session->numSubscriptions++;
- server->numSubscriptions++;
+void
+UA_Session_attachSubscription(UA_Session *session, UA_Subscription *sub) {
+ /* Attach to the session */
+ sub->session = session;
+
+ /* Increase the count */
+ session->subscriptionsSize++;
+
+ /* Increase the number of outstanding retransmissions */
+ session->totalRetransmissionQueueSize += sub->retransmissionQueueSize;
+
+ /* Insert at the end of the subscriptions of the same priority / just before
+ * the subscriptions with the next lower priority. */
+ UA_Subscription *after = NULL;
+ TAILQ_FOREACH(after, &session->subscriptions, sessionListEntry) {
+ if(after->priority < sub->priority) {
+ TAILQ_INSERT_BEFORE(after, sub, sessionListEntry);
+ return;
+ }
+ }
+ TAILQ_INSERT_TAIL(&session->subscriptions, sub, sessionListEntry);
}
-UA_StatusCode
-UA_Session_deleteSubscription(UA_Server *server, UA_Session *session,
- UA_UInt32 subscriptionId) {
- UA_LOCK_ASSERT(server->serviceMutex, 1);
-
- UA_Subscription *sub = UA_Session_getSubscriptionById(session, subscriptionId);
- if(!sub)
- return UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
-
- UA_Subscription_deleteMembers(server, sub);
-
- /* Add a delayed callback to remove the subscription when the currently
- * scheduled jobs have completed. There is no actual delayed callback. Just
- * free the structure. */
- sub->delayedFreePointers.callback = NULL;
- UA_WorkQueue_enqueueDelayed(&server->workQueue, &sub->delayedFreePointers);
-
- /* Remove from the session */
- LIST_REMOVE(sub, listEntry);
- UA_assert(session->numSubscriptions > 0);
- UA_assert(server->numSubscriptions > 0);
- session->numSubscriptions--;
- server->numSubscriptions--;
- return UA_STATUSCODE_GOOD;
+void
+UA_Session_detachSubscription(UA_Server *server, UA_Session *session,
+ UA_Subscription *sub, UA_Boolean releasePublishResponses) {
+ /* Detach from the session */
+ sub->session = NULL;
+ TAILQ_REMOVE(&session->subscriptions, sub, sessionListEntry);
+
+ /* Reduce the count */
+ UA_assert(session->subscriptionsSize > 0);
+ session->subscriptionsSize--;
+
+ /* Reduce the number of outstanding retransmissions */
+ session->totalRetransmissionQueueSize -= sub->retransmissionQueueSize;
+
+ /* Send remaining publish responses if the last subscription was removed */
+ if(!releasePublishResponses || !TAILQ_EMPTY(&session->subscriptions))
+ return;
+ UA_PublishResponseEntry *pre;
+ while((pre = UA_Session_dequeuePublishReq(session))) {
+ UA_PublishResponse *response = &pre->response;
+ response->responseHeader.serviceResult = UA_STATUSCODE_BADNOSUBSCRIPTION;
+ response->responseHeader.timestamp = UA_DateTime_now();
+ sendResponse(server, session, session->header.channel, pre->requestId,
+ (UA_Response*)response, &UA_TYPES[UA_TYPES_PUBLISHRESPONSE]);
+ UA_PublishResponse_clear(response);
+ UA_free(pre);
+ }
}
UA_Subscription *
UA_Session_getSubscriptionById(UA_Session *session, UA_UInt32 subscriptionId) {
UA_Subscription *sub;
- LIST_FOREACH(sub, &session->serverSubscriptions, listEntry) {
+ TAILQ_FOREACH(sub, &session->subscriptions, sessionListEntry) {
+ /* Prevent lookup of subscriptions that are to be deleted with a statuschange */
+ if(sub->statusChange != UA_STATUSCODE_GOOD)
+ continue;
+ if(sub->subscriptionId == subscriptionId)
+ break;
+ }
+ return sub;
+}
+
+UA_Subscription *
+UA_Server_getSubscriptionById(UA_Server *server, UA_UInt32 subscriptionId) {
+ UA_Subscription *sub;
+ LIST_FOREACH(sub, &server->subscriptions, serverListEntry) {
+ /* Prevent lookup of subscriptions that are to be deleted with a statuschange */
+ if(sub->statusChange != UA_STATUSCODE_GOOD)
+ continue;
if(sub->subscriptionId == subscriptionId)
break;
}
@@ -22007,29 +20330,154 @@ UA_Session_dequeuePublishReq(UA_Session *session) {
UA_PublishResponseEntry* entry = SIMPLEQ_FIRST(&session->responseQueue);
if(entry) {
SIMPLEQ_REMOVE_HEAD(&session->responseQueue, listEntry);
- session->numPublishReq--;
+ session->responseQueueSize--;
}
return entry;
}
void
-UA_Session_queuePublishReq(UA_Session *session, UA_PublishResponseEntry* entry, UA_Boolean head) {
+UA_Session_queuePublishReq(UA_Session *session, UA_PublishResponseEntry* entry,
+ UA_Boolean head) {
if(!head)
SIMPLEQ_INSERT_TAIL(&session->responseQueue, entry, listEntry);
else
SIMPLEQ_INSERT_HEAD(&session->responseQueue, entry, listEntry);
- session->numPublishReq++;
+ session->responseQueueSize++;
}
#endif
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/src/server/ua_nodes.c" ***********************************/
+/* Session Handling */
+
+UA_StatusCode
+UA_Server_closeSession(UA_Server *server, const UA_NodeId *sessionId) {
+ UA_LOCK(&server->serviceMutex);
+ session_list_entry *entry;
+ UA_StatusCode res = UA_STATUSCODE_BADSESSIONIDINVALID;
+ LIST_FOREACH(entry, &server->sessions, pointers) {
+ if(UA_NodeId_equal(&entry->session.sessionId, sessionId)) {
+ UA_Server_removeSession(server, entry, UA_DIAGNOSTICEVENT_CLOSE);
+ res = UA_STATUSCODE_GOOD;
+ break;
+ }
+ }
+ UA_UNLOCK(&server->serviceMutex);
+ return res;
+}
+
+UA_StatusCode
+UA_Server_setSessionParameter(UA_Server *server, const UA_NodeId *sessionId,
+ const char *name, const UA_Variant *parameter) {
+ UA_LOCK(&server->serviceMutex);
+ UA_Session *session = UA_Server_getSessionById(server, sessionId);
+ UA_StatusCode res = UA_STATUSCODE_BADSESSIONIDINVALID;
+ if(session)
+ res = UA_KeyValueMap_set(&session->params, &session->paramsSize,
+ name, parameter);
+ UA_UNLOCK(&server->serviceMutex);
+ return res;
+}
+
+void
+UA_Server_deleteSessionParameter(UA_Server *server, const UA_NodeId *sessionId,
+ const char *name) {
+ UA_LOCK(&server->serviceMutex);
+ UA_Session *session = UA_Server_getSessionById(server, sessionId);
+ if(session)
+ UA_KeyValueMap_delete(&session->params, &session->paramsSize, name);
+ UA_UNLOCK(&server->serviceMutex);
+}
+
+UA_StatusCode
+UA_Server_getSessionParameter(UA_Server *server, const UA_NodeId *sessionId,
+ const char *name, UA_Variant *outParameter) {
+ UA_LOCK(&server->serviceMutex);
+ if(!outParameter) {
+ UA_UNLOCK(&server->serviceMutex);
+ return UA_STATUSCODE_BADINTERNALERROR;
+ }
+
+ UA_Session *session = UA_Server_getSessionById(server, sessionId);
+ if(!session) {
+ UA_UNLOCK(&server->serviceMutex);
+ return UA_STATUSCODE_BADSESSIONIDINVALID;
+ }
+
+ const UA_Variant *param =
+ UA_KeyValueMap_get(session->params, session->paramsSize, name);
+ if(!param) {
+ UA_UNLOCK(&server->serviceMutex);
+ return UA_STATUSCODE_BADNOTFOUND;
+ }
+
+ UA_StatusCode res = UA_Variant_copy(param, outParameter);
+ UA_UNLOCK(&server->serviceMutex);
+ return res;
+}
+
+UA_StatusCode
+UA_Server_getSessionScalarParameter(UA_Server *server, const UA_NodeId *sessionId,
+ const char *name, const UA_DataType *type,
+ UA_Variant *outParameter) {
+ UA_LOCK(&server->serviceMutex);
+ if(!outParameter) {
+ UA_UNLOCK(&server->serviceMutex);
+ return UA_STATUSCODE_BADINTERNALERROR;
+ }
+
+ UA_Session *session = UA_Server_getSessionById(server, sessionId);
+ if(!session) {
+ UA_UNLOCK(&server->serviceMutex);
+ return UA_STATUSCODE_BADSESSIONIDINVALID;
+ }
+
+ const UA_Variant *param =
+ UA_KeyValueMap_get(session->params, session->paramsSize, name);
+ if(!param || !UA_Variant_hasScalarType(param, type)) {
+ UA_UNLOCK(&server->serviceMutex);
+ return UA_STATUSCODE_BADNOTFOUND;
+ }
+
+ UA_StatusCode res = UA_Variant_copy(param, outParameter);
+ UA_UNLOCK(&server->serviceMutex);
+ return res;
+}
+
+UA_StatusCode
+UA_Server_getSessionArrayParameter(UA_Server *server, const UA_NodeId *sessionId,
+ const char *name, const UA_DataType *type,
+ UA_Variant *outParameter) {
+ UA_LOCK(&server->serviceMutex);
+ if(!outParameter) {
+ UA_UNLOCK(&server->serviceMutex);
+ return UA_STATUSCODE_BADINTERNALERROR;
+ }
+
+ UA_Session *session = UA_Server_getSessionById(server, sessionId);
+ if(!session) {
+ UA_UNLOCK(&server->serviceMutex);
+ return UA_STATUSCODE_BADSESSIONIDINVALID;
+ }
+
+ const UA_Variant *param =
+ UA_KeyValueMap_get(session->params, session->paramsSize, name);
+ if(!param || !UA_Variant_hasArrayType(param, type)) {
+ UA_UNLOCK(&server->serviceMutex);
+ return UA_STATUSCODE_BADNOTFOUND;
+ }
+
+ UA_StatusCode res = UA_Variant_copy(param, outParameter);
+ UA_UNLOCK(&server->serviceMutex);
+ return res;
+}
+
+/**** amalgamated original file "/src/server/ua_nodes.c" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
- * Copyright 2015-2018 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
+ * Copyright 2015-2018, 2021 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
* Copyright 2015-2016 (c) Sten Grüner
* Copyright 2015 (c) Chris Iatrou
* Copyright 2015, 2017 (c) Florian Palm
@@ -22039,53 +20487,373 @@ UA_Session_queuePublishReq(UA_Session *session, UA_PublishResponseEntry* entry,
*/
-/* ZipTree for the lookup of references by their identifier */
+/*****************/
+/* Node Pointers */
+/*****************/
-static enum ZIP_CMP
+#define UA_NODEPOINTER_MASK 0x03
+#define UA_NODEPOINTER_TAG_IMMEDIATE 0x00
+#define UA_NODEPOINTER_TAG_NODEID 0x01
+#define UA_NODEPOINTER_TAG_EXPANDEDNODEID 0x02
+#define UA_NODEPOINTER_TAG_NODE 0x03
+
+void
+UA_NodePointer_clear(UA_NodePointer *np) {
+ switch(np->immediate & UA_NODEPOINTER_MASK) {
+ case UA_NODEPOINTER_TAG_NODEID:
+ np->immediate &= ~(uintptr_t)UA_NODEPOINTER_MASK;
+ UA_NodeId_delete((UA_NodeId*)(uintptr_t)np->id);
+ break;
+ case UA_NODEPOINTER_TAG_EXPANDEDNODEID:
+ np->immediate &= ~(uintptr_t)UA_NODEPOINTER_MASK;
+ UA_ExpandedNodeId_delete((UA_ExpandedNodeId*)(uintptr_t)
+ np->expandedId);
+ break;
+ default:
+ break;
+ }
+ UA_NodePointer_init(np);
+}
+
+UA_StatusCode
+UA_NodePointer_copy(UA_NodePointer in, UA_NodePointer *out) {
+ UA_StatusCode res = UA_STATUSCODE_GOOD;
+ UA_Byte tag = in.immediate & UA_NODEPOINTER_MASK;
+ in.immediate &= ~(uintptr_t)UA_NODEPOINTER_MASK;
+ switch(tag) {
+ case UA_NODEPOINTER_TAG_NODE:
+ in.id = &in.node->nodeId;
+ goto nodeid; /* fallthrough */
+ case UA_NODEPOINTER_TAG_NODEID:
+ nodeid:
+ out->id = UA_NodeId_new();
+ if(!out->id)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ res = UA_NodeId_copy(in.id, (UA_NodeId*)(uintptr_t)out->id);
+ if(res != UA_STATUSCODE_GOOD) {
+ UA_free((void*)out->immediate);
+ out->immediate = 0;
+ break;
+ }
+ out->immediate |= UA_NODEPOINTER_TAG_NODEID;
+ break;
+ case UA_NODEPOINTER_TAG_EXPANDEDNODEID:
+ out->expandedId = UA_ExpandedNodeId_new();
+ if(!out->expandedId)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ res = UA_ExpandedNodeId_copy(in.expandedId,
+ (UA_ExpandedNodeId*)(uintptr_t)
+ out->expandedId);
+ if(res != UA_STATUSCODE_GOOD) {
+ UA_free((void*)out->immediate);
+ out->immediate = 0;
+ break;
+ }
+ out->immediate |= UA_NODEPOINTER_TAG_EXPANDEDNODEID;
+ break;
+ default:
+ case UA_NODEPOINTER_TAG_IMMEDIATE:
+ *out = in;
+ break;
+ }
+ return res;
+}
+
+UA_Boolean
+UA_NodePointer_isLocal(UA_NodePointer np) {
+ UA_Byte tag = np.immediate & UA_NODEPOINTER_MASK;
+ return (tag != UA_NODEPOINTER_TAG_EXPANDEDNODEID);
+}
+
+UA_Order
+UA_NodePointer_order(UA_NodePointer p1, UA_NodePointer p2) {
+ if(p1.immediate == p2.immediate)
+ return UA_ORDER_EQ;
+
+ /* Extract the tag and resolve pointers to nodes */
+ UA_Byte tag1 = p1.immediate & UA_NODEPOINTER_MASK;
+ if(tag1 == UA_NODEPOINTER_TAG_NODE) {
+ p1 = UA_NodePointer_fromNodeId(&p1.node->nodeId);
+ tag1 = p1.immediate & UA_NODEPOINTER_MASK;
+ }
+ UA_Byte tag2 = p2.immediate & UA_NODEPOINTER_MASK;
+ if(tag2 == UA_NODEPOINTER_TAG_NODE) {
+ p2 = UA_NodePointer_fromNodeId(&p2.node->nodeId);
+ tag2 = p2.immediate & UA_NODEPOINTER_MASK;
+ }
+
+ /* Different tags, cannot be identical */
+ if(tag1 != tag2)
+ return (tag1 > tag2) ? UA_ORDER_MORE : UA_ORDER_LESS;
+
+ /* Immediate */
+ if(UA_LIKELY(tag1 == UA_NODEPOINTER_TAG_IMMEDIATE))
+ return (p1.immediate > p2.immediate) ?
+ UA_ORDER_MORE : UA_ORDER_LESS;
+
+ /* Compare from pointers */
+ p1.immediate &= ~(uintptr_t)UA_NODEPOINTER_MASK;
+ p2.immediate &= ~(uintptr_t)UA_NODEPOINTER_MASK;
+ if(tag1 == UA_NODEPOINTER_TAG_EXPANDEDNODEID)
+ return UA_ExpandedNodeId_order(p1.expandedId, p2.expandedId);
+ return UA_NodeId_order(p1.id, p2.id);
+}
+
+UA_NodePointer
+UA_NodePointer_fromNodeId(const UA_NodeId *id) {
+ UA_NodePointer np;
+ if(id->identifierType != UA_NODEIDTYPE_NUMERIC) {
+ np.id = id;
+ np.immediate |= UA_NODEPOINTER_TAG_NODEID;
+ return np;
+ }
+
+#if SIZE_MAX > UA_UINT32_MAX
+ /* 64bit: 4 Byte for the numeric identifier + 2 Byte for the namespaceIndex
+ * + 1 Byte for the tagging bit (zero) */
+ np.immediate = ((uintptr_t)id->identifier.numeric) << 32;
+ np.immediate |= ((uintptr_t)id->namespaceIndex) << 8;
+#else
+ /* 32bit: 3 Byte for the numeric identifier + 6 Bit for the namespaceIndex
+ * + 2 Bit for the tagging bit (zero) */
+ if(id->namespaceIndex < (0x01 << 6) &&
+ id->identifier.numeric < (0x01 << 24)) {
+ np.immediate = ((uintptr_t)id->identifier.numeric) << 8;
+ np.immediate |= ((uintptr_t)id->namespaceIndex) << 2;
+ } else {
+ np.id = id;
+ np.immediate |= UA_NODEPOINTER_TAG_NODEID;
+ }
+#endif
+ return np;
+}
+
+UA_NodeId
+UA_NodePointer_toNodeId(UA_NodePointer np) {
+ UA_Byte tag = np.immediate & UA_NODEPOINTER_MASK;
+ np.immediate &= ~(uintptr_t)UA_NODEPOINTER_MASK;
+ switch(tag) {
+ case UA_NODEPOINTER_TAG_NODE:
+ return np.node->nodeId;
+ case UA_NODEPOINTER_TAG_NODEID:
+ return *np.id;
+ case UA_NODEPOINTER_TAG_EXPANDEDNODEID:
+ return np.expandedId->nodeId;
+ default:
+ case UA_NODEPOINTER_TAG_IMMEDIATE:
+ break;
+ }
+
+ UA_NodeId id;
+ id.identifierType = UA_NODEIDTYPE_NUMERIC;
+#if SIZE_MAX > UA_UINT32_MAX /* 64bit */
+ id.namespaceIndex = (UA_UInt16)(np.immediate >> 8);
+ id.identifier.numeric = (UA_UInt32)(np.immediate >> 32);
+#else /* 32bit */
+ id.namespaceIndex = ((UA_Byte)np.immediate) >> 2;
+ id.identifier.numeric = np.immediate >> 8;
+#endif
+ return id;
+}
+
+UA_NodePointer
+UA_NodePointer_fromExpandedNodeId(const UA_ExpandedNodeId *id) {
+ if(!UA_ExpandedNodeId_isLocal(id)) {
+ UA_NodePointer np;
+ np.expandedId = id;
+ np.immediate |= UA_NODEPOINTER_TAG_EXPANDEDNODEID;
+ return np;
+ }
+ return UA_NodePointer_fromNodeId(&id->nodeId);
+}
+
+UA_ExpandedNodeId
+UA_NodePointer_toExpandedNodeId(UA_NodePointer np) {
+ /* Resolve node pointer to get the NodeId */
+ UA_Byte tag = np.immediate & UA_NODEPOINTER_MASK;
+ if(tag == UA_NODEPOINTER_TAG_NODE) {
+ np = UA_NodePointer_fromNodeId(&np.node->nodeId);
+ tag = np.immediate & UA_NODEPOINTER_MASK;
+ }
+
+ /* ExpandedNodeId, make a shallow copy */
+ if(tag == UA_NODEPOINTER_TAG_EXPANDEDNODEID) {
+ np.immediate &= ~(uintptr_t)UA_NODEPOINTER_MASK;
+ return *np.expandedId;
+ }
+
+ /* NodeId, either immediate or via a pointer */
+ UA_ExpandedNodeId en;
+ UA_ExpandedNodeId_init(&en);
+ en.nodeId = UA_NodePointer_toNodeId(np);
+ return en;
+}
+
+/**************/
+/* References */
+/**************/
+
+static UA_StatusCode
+addReferenceTarget(UA_NodeReferenceKind *refs, UA_NodePointer target,
+ UA_UInt32 targetNameHash);
+
+static enum aa_cmp
cmpRefTargetId(const void *a, const void *b) {
- const UA_ReferenceTarget *aa = (const UA_ReferenceTarget*)a;
- const UA_ReferenceTarget *bb = (const UA_ReferenceTarget*)b;
+ const UA_ReferenceTargetTreeElem *aa = (const UA_ReferenceTargetTreeElem*)a;
+ const UA_ReferenceTargetTreeElem *bb = (const UA_ReferenceTargetTreeElem*)b;
if(aa->targetIdHash < bb->targetIdHash)
- return ZIP_CMP_LESS;
+ return AA_CMP_LESS;
if(aa->targetIdHash > bb->targetIdHash)
- return ZIP_CMP_MORE;
- return (enum ZIP_CMP)UA_ExpandedNodeId_order(&aa->targetId, &bb->targetId);
+ return AA_CMP_MORE;
+ return (enum aa_cmp)UA_NodePointer_order(aa->target.targetId,
+ bb->target.targetId);
}
-ZIP_IMPL(UA_ReferenceTargetIdTree, UA_ReferenceTarget, idTreeFields,
- UA_ReferenceTarget, idTreeFields, cmpRefTargetId)
-
-/* ZipTree for the lookup of references by their BrowseName. UA_ReferenceTarget
- * stores only the hash. A full node lookup is in order to do the actual
- * comparison. */
-
-static enum ZIP_CMP
-cmpRefTargetName(const UA_UInt32 *nameHashA, const UA_UInt32 *nameHashB) {
+static enum aa_cmp
+cmpRefTargetName(const void *a, const void *b) {
+ const UA_UInt32 *nameHashA = (const UA_UInt32*)a;
+ const UA_UInt32 *nameHashB = (const UA_UInt32*)b;
if(*nameHashA < *nameHashB)
- return ZIP_CMP_LESS;
+ return AA_CMP_LESS;
if(*nameHashA > *nameHashB)
- return ZIP_CMP_MORE;
- return ZIP_CMP_EQ;
+ return AA_CMP_MORE;
+ return AA_CMP_EQ;
+}
+
+/* Reusable binary search tree "heads". Just switch out the root pointer. */
+static const struct aa_head refIdTree =
+ { NULL, cmpRefTargetId, offsetof(UA_ReferenceTargetTreeElem, idTreeEntry), 0 };
+const struct aa_head refNameTree =
+ { NULL, cmpRefTargetName, offsetof(UA_ReferenceTargetTreeElem, nameTreeEntry),
+ offsetof(UA_ReferenceTarget, targetNameHash) };
+
+const UA_ReferenceTarget *
+UA_NodeReferenceKind_iterate(const UA_NodeReferenceKind *rk,
+ const UA_ReferenceTarget *prev) {
+ /* Return from the tree */
+ if(rk->hasRefTree) {
+ const struct aa_head _refIdTree =
+ { rk->targets.tree.idTreeRoot, cmpRefTargetId,
+ offsetof(UA_ReferenceTargetTreeElem, idTreeEntry), 0 };
+ if(prev == NULL)
+ return (const UA_ReferenceTarget*)aa_min(&_refIdTree);
+ return (const UA_ReferenceTarget*)aa_next(&_refIdTree, prev);
+ }
+ if(prev == NULL) /* Return start of the array */
+ return rk->targets.array;
+ if(prev + 1 >= &rk->targets.array[rk->targetsSize])
+ return NULL; /* End of the array */
+ return prev + 1; /* Next element in the array */
+}
+
+/* Also deletes the elements of the tree */
+static void
+moveTreeToArray(UA_ReferenceTarget *array, size_t *pos,
+ struct aa_entry *entry) {
+ if(!entry)
+ return;
+ UA_ReferenceTargetTreeElem *elem = (UA_ReferenceTargetTreeElem*)
+ ((uintptr_t)entry - offsetof(UA_ReferenceTargetTreeElem, idTreeEntry));
+ moveTreeToArray(array, pos, elem->idTreeEntry.left);
+ moveTreeToArray(array, pos, elem->idTreeEntry.right);
+ array[*pos] = elem->target;
+ (*pos)++;
+ UA_free(elem);
}
-ZIP_IMPL(UA_ReferenceTargetNameTree, UA_ReferenceTarget, nameTreeFields,
- UA_UInt32, targetNameHash, cmpRefTargetName)
+UA_StatusCode
+UA_NodeReferenceKind_switch(UA_NodeReferenceKind *rk) {
+ if(rk->hasRefTree) {
+ /* From tree to array */
+ UA_ReferenceTarget *array = (UA_ReferenceTarget*)
+ UA_malloc(sizeof(UA_ReferenceTarget) * rk->targetsSize);
+ if(!array)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ size_t pos = 0;
+ moveTreeToArray(array, &pos, rk->targets.tree.idTreeRoot);
+ rk->targets.array = array;
+ rk->hasRefTree = false;
+ return UA_STATUSCODE_GOOD;
+ }
+
+ /* From array to tree */
+ UA_NodeReferenceKind newRk = *rk;
+ newRk.hasRefTree = true;
+ newRk.targets.tree.idTreeRoot = NULL;
+ newRk.targets.tree.nameTreeRoot = NULL;
+ for(size_t i = 0; i < rk->targetsSize; i++) {
+ UA_StatusCode res =
+ addReferenceTarget(&newRk, rk->targets.array[i].targetId,
+ rk->targets.array[i].targetNameHash);
+ if(res != UA_STATUSCODE_GOOD) {
+ struct aa_head _refIdTree = refIdTree;
+ _refIdTree.root = newRk.targets.tree.idTreeRoot;
+ while(_refIdTree.root) {
+ UA_ReferenceTargetTreeElem *elem = (UA_ReferenceTargetTreeElem*)
+ ((uintptr_t)_refIdTree.root -
+ offsetof(UA_ReferenceTargetTreeElem, idTreeEntry));
+ aa_remove(&_refIdTree, elem);
+ UA_NodePointer_clear(&elem->target.targetId);
+ UA_free(elem);
+ }
+ return res;
+ }
+ }
+ for(size_t i = 0; i < rk->targetsSize; i++)
+ UA_NodePointer_clear(&rk->targets.array[i].targetId);
+ UA_free(rk->targets.array);
+ *rk = newRk;
+ return UA_STATUSCODE_GOOD;
+}
+
+const UA_ReferenceTarget *
+UA_NodeReferenceKind_findTarget(const UA_NodeReferenceKind *rk,
+ const UA_ExpandedNodeId *targetId) {
+ UA_NodePointer targetP = UA_NodePointer_fromExpandedNodeId(targetId);
+
+ /* Return from the tree */
+ if(rk->hasRefTree) {
+ UA_ReferenceTargetTreeElem tmpTarget;
+ tmpTarget.target.targetId = targetP;
+ tmpTarget.targetIdHash = UA_ExpandedNodeId_hash(targetId);
+ const struct aa_head _refIdTree =
+ { rk->targets.tree.idTreeRoot, cmpRefTargetId,
+ offsetof(UA_ReferenceTargetTreeElem, idTreeEntry), 0 };
+ return (const UA_ReferenceTarget*)aa_find(&_refIdTree, &tmpTarget);
+ }
+
+ /* Return from the array */
+ for(size_t i = 0; i < rk->targetsSize; i++) {
+ if(UA_NodePointer_equal(targetP, rk->targets.array[i].targetId))
+ return &rk->targets.array[i];
+ }
+ return NULL;
+}
+
+const UA_Node *
+UA_NODESTORE_GETFROMREF(UA_Server *server, UA_NodePointer target) {
+ if(!UA_NodePointer_isLocal(target))
+ return NULL;
+ UA_NodeId id = UA_NodePointer_toNodeId(target);
+ return UA_NODESTORE_GET(server, &id);
+}
/* General node handling methods. There is no UA_Node_new() method here.
* Creating nodes is part of the Nodestore layer */
void UA_Node_clear(UA_Node *node) {
- /* Delete standard content */
- UA_NodeId_clear(&node->nodeId);
- UA_QualifiedName_clear(&node->browseName);
- UA_LocalizedText_clear(&node->displayName);
- UA_LocalizedText_clear(&node->description);
-
/* Delete references */
UA_Node_deleteReferences(node);
+ /* Delete other head content */
+ UA_NodeHead *head = &node->head;
+ UA_NodeId_clear(&head->nodeId);
+ UA_QualifiedName_clear(&head->browseName);
+ UA_LocalizedText_clear(&head->displayName);
+ UA_LocalizedText_clear(&head->description);
+
/* Delete unique content of the nodeclass */
- switch(node->nodeClass) {
+ switch(head->nodeClass) {
case UA_NODECLASS_OBJECT:
break;
case UA_NODECLASS_METHOD:
@@ -22094,7 +20862,7 @@ void UA_Node_clear(UA_Node *node) {
break;
case UA_NODECLASS_VARIABLE:
case UA_NODECLASS_VARIABLETYPE: {
- UA_VariableNode *p = (UA_VariableNode*)node;
+ UA_VariableNode *p = &node->variableNode;
UA_NodeId_clear(&p->dataType);
UA_Array_delete(p->arrayDimensions, p->arrayDimensionsSize,
&UA_TYPES[UA_TYPES_INT32]);
@@ -22105,7 +20873,7 @@ void UA_Node_clear(UA_Node *node) {
break;
}
case UA_NODECLASS_REFERENCETYPE: {
- UA_ReferenceTypeNode *p = (UA_ReferenceTypeNode*)node;
+ UA_ReferenceTypeNode *p = &node->referenceTypeNode;
UA_LocalizedText_clear(&p->inverseName);
break;
}
@@ -22126,10 +20894,9 @@ UA_ObjectNode_copy(const UA_ObjectNode *src, UA_ObjectNode *dst) {
static UA_StatusCode
UA_CommonVariableNode_copy(const UA_VariableNode *src, UA_VariableNode *dst) {
- UA_StatusCode retval = UA_Array_copy(src->arrayDimensions,
- src->arrayDimensionsSize,
- (void**)&dst->arrayDimensions,
- &UA_TYPES[UA_TYPES_INT32]);
+ UA_StatusCode retval =
+ UA_Array_copy(src->arrayDimensions, src->arrayDimensionsSize,
+ (void**)&dst->arrayDimensions, &UA_TYPES[UA_TYPES_INT32]);
if(retval != UA_STATUSCODE_GOOD)
return retval;
dst->arrayDimensionsSize = src->arrayDimensionsSize;
@@ -22147,20 +20914,18 @@ UA_CommonVariableNode_copy(const UA_VariableNode *src, UA_VariableNode *dst) {
static UA_StatusCode
UA_VariableNode_copy(const UA_VariableNode *src, UA_VariableNode *dst) {
- UA_StatusCode retval = UA_CommonVariableNode_copy(src, dst);
dst->accessLevel = src->accessLevel;
dst->minimumSamplingInterval = src->minimumSamplingInterval;
dst->historizing = src->historizing;
- return retval;
+ dst->isDynamic = src->isDynamic;
+ return UA_CommonVariableNode_copy(src, dst);
}
static UA_StatusCode
UA_VariableTypeNode_copy(const UA_VariableTypeNode *src,
UA_VariableTypeNode *dst) {
- UA_StatusCode retval = UA_CommonVariableNode_copy((const UA_VariableNode*)src,
- (UA_VariableNode*)dst);
dst->isAbstract = src->isAbstract;
- return retval;
+ return UA_CommonVariableNode_copy((const UA_VariableNode*)src, (UA_VariableNode*)dst);
}
static UA_StatusCode
@@ -22183,11 +20948,11 @@ UA_ObjectTypeNode_copy(const UA_ObjectTypeNode *src, UA_ObjectTypeNode *dst) {
static UA_StatusCode
UA_ReferenceTypeNode_copy(const UA_ReferenceTypeNode *src,
UA_ReferenceTypeNode *dst) {
- UA_StatusCode retval = UA_LocalizedText_copy(&src->inverseName,
- &dst->inverseName);
dst->isAbstract = src->isAbstract;
dst->symmetric = src->symmetric;
- return retval;
+ dst->referenceTypeIndex = src->referenceTypeIndex;
+ dst->subTypes = src->subTypes;
+ return UA_LocalizedText_copy(&src->inverseName, &dst->inverseName);
}
static UA_StatusCode
@@ -22205,121 +20970,82 @@ UA_ViewNode_copy(const UA_ViewNode *src, UA_ViewNode *dst) {
UA_StatusCode
UA_Node_copy(const UA_Node *src, UA_Node *dst) {
- if(src->nodeClass != dst->nodeClass)
+ const UA_NodeHead *srchead = &src->head;
+ UA_NodeHead *dsthead = &dst->head;
+ if(srchead->nodeClass != dsthead->nodeClass)
return UA_STATUSCODE_BADINTERNALERROR;
/* Copy standard content */
- UA_StatusCode retval = UA_NodeId_copy(&src->nodeId, &dst->nodeId);
- retval |= UA_QualifiedName_copy(&src->browseName, &dst->browseName);
- retval |= UA_LocalizedText_copy(&src->displayName, &dst->displayName);
- retval |= UA_LocalizedText_copy(&src->description, &dst->description);
- dst->writeMask = src->writeMask;
- dst->context = src->context;
- dst->constructed = src->constructed;
+ UA_StatusCode retval = UA_NodeId_copy(&srchead->nodeId, &dsthead->nodeId);
+ retval |= UA_QualifiedName_copy(&srchead->browseName, &dsthead->browseName);
+ retval |= UA_LocalizedText_copy(&srchead->displayName, &dsthead->displayName);
+ retval |= UA_LocalizedText_copy(&srchead->description, &dsthead->description);
+ dsthead->writeMask = srchead->writeMask;
+ dsthead->context = srchead->context;
+ dsthead->constructed = srchead->constructed;
+#ifdef UA_ENABLE_SUBSCRIPTIONS
+ dsthead->monitoredItems = srchead->monitoredItems;
+#endif
if(retval != UA_STATUSCODE_GOOD) {
UA_Node_clear(dst);
return retval;
}
/* Copy the references */
- dst->references = NULL;
- if(src->referencesSize > 0) {
- dst->references = (UA_NodeReferenceKind*)
- UA_calloc(src->referencesSize, sizeof(UA_NodeReferenceKind));
- if(!dst->references) {
+ dsthead->references = NULL;
+ if(srchead->referencesSize > 0) {
+ dsthead->references = (UA_NodeReferenceKind*)
+ UA_calloc(srchead->referencesSize, sizeof(UA_NodeReferenceKind));
+ if(!dsthead->references) {
UA_Node_clear(dst);
return UA_STATUSCODE_BADOUTOFMEMORY;
}
- dst->referencesSize = src->referencesSize;
+ dsthead->referencesSize = srchead->referencesSize;
- for(size_t i = 0; i < src->referencesSize; ++i) {
- UA_NodeReferenceKind *srefs = &src->references[i];
- UA_NodeReferenceKind *drefs = &dst->references[i];
+ for(size_t i = 0; i < srchead->referencesSize; ++i) {
+ UA_NodeReferenceKind *srefs = &srchead->references[i];
+ UA_NodeReferenceKind *drefs = &dsthead->references[i];
+ drefs->referenceTypeIndex = srefs->referenceTypeIndex;
drefs->isInverse = srefs->isInverse;
- ZIP_INIT(&drefs->refTargetsIdTree);
- retval = UA_NodeId_copy(&srefs->referenceTypeId, &drefs->referenceTypeId);
- if(retval != UA_STATUSCODE_GOOD)
- break;
- drefs->refTargets = (UA_ReferenceTarget*)
- UA_malloc(srefs->refTargetsSize* sizeof(UA_ReferenceTarget));
- if(!drefs->refTargets) {
- UA_NodeId_clear(&drefs->referenceTypeId);
- break;
- }
- uintptr_t arraydiff = (uintptr_t)drefs->refTargets - (uintptr_t)srefs->refTargets;
- for(size_t j = 0; j < srefs->refTargetsSize; j++) {
- UA_ReferenceTarget *srefTarget = &srefs->refTargets[j];
- UA_ReferenceTarget *drefTarget = &drefs->refTargets[j];
- retval |= UA_ExpandedNodeId_copy(&srefTarget->targetId, &drefTarget->targetId);
- drefTarget->targetIdHash = srefTarget->targetIdHash;
- drefTarget->targetNameHash = srefTarget->targetNameHash;
- ZIP_RANK(drefTarget, idTreeFields) = ZIP_RANK(srefTarget, idTreeFields);
- /* IdTree Fields */
- ZIP_RIGHT(drefTarget, idTreeFields) = NULL;
- if(ZIP_RIGHT(srefTarget, idTreeFields))
- ZIP_RIGHT(drefTarget, idTreeFields) = (UA_ReferenceTarget*)
- ((uintptr_t)ZIP_RIGHT(srefTarget, idTreeFields) + arraydiff);
- ZIP_LEFT(drefTarget, idTreeFields) = NULL;
- if(ZIP_LEFT(srefTarget, idTreeFields))
- ZIP_LEFT(drefTarget, idTreeFields) = (UA_ReferenceTarget*)
- ((uintptr_t)ZIP_LEFT(srefTarget, idTreeFields) + arraydiff);
- /* NameTree Fields */
- ZIP_RIGHT(drefTarget, nameTreeFields) = NULL;
- if(ZIP_RIGHT(srefTarget, nameTreeFields))
- ZIP_RIGHT(drefTarget, nameTreeFields) = (UA_ReferenceTarget*)
- ((uintptr_t)ZIP_RIGHT(srefTarget, nameTreeFields) + arraydiff);
- ZIP_LEFT(drefTarget, nameTreeFields) = NULL;
- if(ZIP_LEFT(srefTarget, nameTreeFields))
- ZIP_LEFT(drefTarget, nameTreeFields) = (UA_ReferenceTarget*)
- ((uintptr_t)ZIP_LEFT(srefTarget, nameTreeFields) + arraydiff);
- }
- /* IdTree Root */
- ZIP_ROOT(&drefs->refTargetsIdTree) = NULL;
- if(ZIP_ROOT(&srefs->refTargetsIdTree))
- ZIP_ROOT(&drefs->refTargetsIdTree) = (UA_ReferenceTarget*)
- ((uintptr_t)ZIP_ROOT(&srefs->refTargetsIdTree) + arraydiff);
- /* NameTree Root */
- ZIP_ROOT(&drefs->refTargetsNameTree) = NULL;
- if(ZIP_ROOT(&srefs->refTargetsNameTree))
- ZIP_ROOT(&drefs->refTargetsNameTree) = (UA_ReferenceTarget*)
- ((uintptr_t)ZIP_ROOT(&srefs->refTargetsNameTree) + arraydiff);
-
- drefs->refTargetsSize = srefs->refTargetsSize;
- if(retval != UA_STATUSCODE_GOOD)
- break;
- }
+ drefs->hasRefTree = srefs->hasRefTree; /* initially empty */
- if(retval != UA_STATUSCODE_GOOD) {
- UA_Node_clear(dst);
- return retval;
+ /* Copy all the targets */
+ const UA_ReferenceTarget *t = NULL;
+ while((t = UA_NodeReferenceKind_iterate(srefs, t))) {
+ retval = addReferenceTarget(drefs, t->targetId, t->targetNameHash);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_Node_clear(dst);
+ return retval;
+ }
+ }
}
}
/* Copy unique content of the nodeclass */
- switch(src->nodeClass) {
+ switch(src->head.nodeClass) {
case UA_NODECLASS_OBJECT:
- retval = UA_ObjectNode_copy((const UA_ObjectNode*)src, (UA_ObjectNode*)dst);
+ retval = UA_ObjectNode_copy(&src->objectNode, &dst->objectNode);
break;
case UA_NODECLASS_VARIABLE:
- retval = UA_VariableNode_copy((const UA_VariableNode*)src, (UA_VariableNode*)dst);
+ retval = UA_VariableNode_copy(&src->variableNode, &dst->variableNode);
break;
case UA_NODECLASS_METHOD:
- retval = UA_MethodNode_copy((const UA_MethodNode*)src, (UA_MethodNode*)dst);
+ retval = UA_MethodNode_copy(&src->methodNode, &dst->methodNode);
break;
case UA_NODECLASS_OBJECTTYPE:
- retval = UA_ObjectTypeNode_copy((const UA_ObjectTypeNode*)src, (UA_ObjectTypeNode*)dst);
+ retval = UA_ObjectTypeNode_copy(&src->objectTypeNode, &dst->objectTypeNode);
break;
case UA_NODECLASS_VARIABLETYPE:
- retval = UA_VariableTypeNode_copy((const UA_VariableTypeNode*)src, (UA_VariableTypeNode*)dst);
+ retval = UA_VariableTypeNode_copy(&src->variableTypeNode, &dst->variableTypeNode);
break;
case UA_NODECLASS_REFERENCETYPE:
- retval = UA_ReferenceTypeNode_copy((const UA_ReferenceTypeNode*)src, (UA_ReferenceTypeNode*)dst);
+ retval = UA_ReferenceTypeNode_copy(&src->referenceTypeNode, &dst->referenceTypeNode);
break;
case UA_NODECLASS_DATATYPE:
- retval = UA_DataTypeNode_copy((const UA_DataTypeNode*)src, (UA_DataTypeNode*)dst);
+ retval = UA_DataTypeNode_copy(&src->dataTypeNode, &dst->dataTypeNode);
break;
case UA_NODECLASS_VIEW:
- retval = UA_ViewNode_copy((const UA_ViewNode*)src, (UA_ViewNode*)dst);
+ retval = UA_ViewNode_copy(&src->viewNode, &dst->viewNode);
break;
default:
break;
@@ -22333,9 +21059,8 @@ UA_Node_copy(const UA_Node *src, UA_Node *dst) {
UA_Node *
UA_Node_copy_alloc(const UA_Node *src) {
- /* use dstPtr to trick static code analysis in accepting dirty cast */
size_t nodesize = 0;
- switch(src->nodeClass) {
+ switch(src->head.nodeClass) {
case UA_NODECLASS_OBJECT:
nodesize = sizeof(UA_ObjectNode);
break;
@@ -22364,11 +21089,11 @@ UA_Node_copy_alloc(const UA_Node *src) {
return NULL;
}
- UA_Node *dst = (UA_Node*)UA_calloc(1,nodesize);
+ UA_Node *dst = (UA_Node*)UA_calloc(1, nodesize);
if(!dst)
return NULL;
- dst->nodeClass = src->nodeClass;
+ dst->head.nodeClass = src->head.nodeClass;
UA_StatusCode retval = UA_Node_copy(src, dst);
if(retval != UA_STATUSCODE_GOOD) {
@@ -22382,24 +21107,19 @@ UA_Node_copy_alloc(const UA_Node *src) {
/******************************/
static UA_StatusCode
-copyStandardAttributes(UA_Node *node, const UA_NodeAttributes *attr) {
- /* retval = UA_NodeId_copy(&item->requestedNewNodeId.nodeId, &node->nodeId); */
- /* retval |= UA_QualifiedName_copy(&item->browseName, &node->browseName); */
-
- UA_StatusCode retval;
- /* The new nodeset format has optional display name.
- * See https://github.com/open62541/open62541/issues/2627
- * If display name is NULL, then we take the name part of the browse name */
- if (attr->displayName.text.length == 0) {
- retval = UA_String_copy(&node->browseName.name,
- &node->displayName.text);
- } else {
- retval = UA_LocalizedText_copy(&attr->displayName,
- &node->displayName);
- retval |= UA_LocalizedText_copy(&attr->description, &node->description);
- }
-
- node->writeMask = attr->writeMask;
+copyStandardAttributes(UA_NodeHead *head, const UA_NodeAttributes *attr) {
+ /* UA_NodeId_copy(&item->requestedNewNodeId.nodeId, &node->nodeId); */
+ /* UA_QualifiedName_copy(&item->browseName, &node->browseName); */
+
+ head->writeMask = attr->writeMask;
+ UA_StatusCode retval = UA_LocalizedText_copy(&attr->description, &head->description);
+ /* The new nodeset format has optional display names:
+ * https://github.com/open62541/open62541/issues/2627. If the display name
+ * is NULL, take the name part of the browse name */
+ if(attr->displayName.text.length == 0)
+ retval |= UA_String_copy(&head->browseName.name, &head->displayName.text);
+ else
+ retval |= UA_LocalizedText_copy(&attr->displayName, &head->displayName);
return retval;
}
@@ -22494,50 +21214,47 @@ copyMethodNodeAttributes(UA_MethodNode *mnode,
}
UA_StatusCode
-UA_Node_setAttributes(UA_Node *node, const void *attributes,
- const UA_DataType *attributeType) {
+UA_Node_setAttributes(UA_Node *node, const void *attributes, const UA_DataType *attributeType) {
/* Copy the attributes into the node */
UA_StatusCode retval = UA_STATUSCODE_GOOD;
- switch(node->nodeClass) {
+ switch(node->head.nodeClass) {
case UA_NODECLASS_OBJECT:
CHECK_ATTRIBUTES(OBJECTATTRIBUTES);
- retval = copyObjectNodeAttributes((UA_ObjectNode*)node,
+ retval = copyObjectNodeAttributes(&node->objectNode,
(const UA_ObjectAttributes*)attributes);
break;
case UA_NODECLASS_VARIABLE:
CHECK_ATTRIBUTES(VARIABLEATTRIBUTES);
- retval = copyVariableNodeAttributes((UA_VariableNode*)node,
+ retval = copyVariableNodeAttributes(&node->variableNode,
(const UA_VariableAttributes*)attributes);
break;
case UA_NODECLASS_OBJECTTYPE:
CHECK_ATTRIBUTES(OBJECTTYPEATTRIBUTES);
- retval = copyObjectTypeNodeAttributes((UA_ObjectTypeNode*)node,
+ retval = copyObjectTypeNodeAttributes(&node->objectTypeNode,
(const UA_ObjectTypeAttributes*)attributes);
break;
case UA_NODECLASS_VARIABLETYPE:
CHECK_ATTRIBUTES(VARIABLETYPEATTRIBUTES);
- retval = copyVariableTypeNodeAttributes((UA_VariableTypeNode*)node,
+ retval = copyVariableTypeNodeAttributes(&node->variableTypeNode,
(const UA_VariableTypeAttributes*)attributes);
break;
case UA_NODECLASS_REFERENCETYPE:
CHECK_ATTRIBUTES(REFERENCETYPEATTRIBUTES);
- retval = copyReferenceTypeNodeAttributes((UA_ReferenceTypeNode*)node,
+ retval = copyReferenceTypeNodeAttributes(&node->referenceTypeNode,
(const UA_ReferenceTypeAttributes*)attributes);
break;
case UA_NODECLASS_DATATYPE:
CHECK_ATTRIBUTES(DATATYPEATTRIBUTES);
- retval = copyDataTypeNodeAttributes((UA_DataTypeNode*)node,
+ retval = copyDataTypeNodeAttributes(&node->dataTypeNode,
(const UA_DataTypeAttributes*)attributes);
break;
case UA_NODECLASS_VIEW:
CHECK_ATTRIBUTES(VIEWATTRIBUTES);
- retval = copyViewNodeAttributes((UA_ViewNode*)node,
- (const UA_ViewAttributes*)attributes);
+ retval = copyViewNodeAttributes(&node->viewNode, (const UA_ViewAttributes*)attributes);
break;
case UA_NODECLASS_METHOD:
CHECK_ATTRIBUTES(METHODATTRIBUTES);
- retval = copyMethodNodeAttributes((UA_MethodNode*)node,
- (const UA_MethodAttributes*)attributes);
+ retval = copyMethodNodeAttributes(&node->methodNode, (const UA_MethodAttributes*)attributes);
break;
case UA_NODECLASS_UNSPECIFIED:
default:
@@ -22545,7 +21262,7 @@ UA_Node_setAttributes(UA_Node *node, const void *attributes,
}
if(retval == UA_STATUSCODE_GOOD)
- retval = copyStandardAttributes(node, (const UA_NodeAttributes*)attributes);
+ retval = copyStandardAttributes(&node->head, (const UA_NodeAttributes*)attributes);
if(retval != UA_STATUSCODE_GOOD)
UA_Node_clear(node);
return retval;
@@ -22555,253 +21272,270 @@ UA_Node_setAttributes(UA_Node *node, const void *attributes,
/* Manage References */
/*********************/
-
static UA_StatusCode
-resizeReferenceTargets(UA_NodeReferenceKind *refs, size_t newSize) {
-
- UA_ReferenceTarget *targets = (UA_ReferenceTarget*)
- UA_realloc(refs->refTargets, newSize * sizeof(UA_ReferenceTarget));
- if(!targets)
- return UA_STATUSCODE_BADOUTOFMEMORY;
-
- /* Repair the pointers in the tree for the realloced array */
- uintptr_t arraydiff = (uintptr_t)targets - (uintptr_t)refs->refTargets;
- if(arraydiff != 0) {
- for(size_t i = 0; i < refs->refTargetsSize; i++) {
- if(targets[i].idTreeFields.zip_left)
- targets[i].idTreeFields.zip_left = (UA_ReferenceTarget*)
- ((uintptr_t)targets[i].idTreeFields.zip_left + arraydiff);
- if(targets[i].idTreeFields.zip_right)
- targets[i].idTreeFields.zip_right = (UA_ReferenceTarget*)
- ((uintptr_t)targets[i].idTreeFields.zip_right + arraydiff);
- if(targets[i].nameTreeFields.zip_left)
- targets[i].nameTreeFields.zip_left = (UA_ReferenceTarget*)
- ((uintptr_t)targets[i].nameTreeFields.zip_left + arraydiff);
- if(targets[i].nameTreeFields.zip_right)
- targets[i].nameTreeFields.zip_right = (UA_ReferenceTarget*)
- ((uintptr_t)targets[i].nameTreeFields.zip_right + arraydiff);
- }
- }
-
- if(refs->refTargetsIdTree.zip_root)
- refs->refTargetsIdTree.zip_root = (UA_ReferenceTarget*)
- ((uintptr_t)refs->refTargetsIdTree.zip_root + arraydiff);
- if(refs->refTargetsNameTree.zip_root)
- refs->refTargetsNameTree.zip_root = (UA_ReferenceTarget*)
- ((uintptr_t)refs->refTargetsNameTree.zip_root + arraydiff);
- refs->refTargets = targets;
- return UA_STATUSCODE_GOOD;
-}
+addReferenceTarget(UA_NodeReferenceKind *rk, UA_NodePointer targetId,
+ UA_UInt32 targetNameHash) {
+ /* Insert into array */
+ if(!rk->hasRefTree) {
+ UA_ReferenceTarget *newRefs = (UA_ReferenceTarget*)
+ UA_realloc(rk->targets.array,
+ sizeof(UA_ReferenceTarget) * (rk->targetsSize + 1));
+ if(!newRefs)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ rk->targets.array = newRefs;
+ UA_StatusCode retval =
+ UA_NodePointer_copy(targetId,
+ &rk->targets.array[rk->targetsSize].targetId);
+ rk->targets.array[rk->targetsSize].targetNameHash = targetNameHash;
+ if(retval != UA_STATUSCODE_GOOD) {
+ if(rk->targetsSize == 0) {
+ UA_free(rk->targets.array);
+ rk->targets.array = NULL;
+ }
+ return retval;
+ }
+ rk->targetsSize++;
+ return UA_STATUSCODE_GOOD;
+ }
-static UA_StatusCode
-addReferenceTarget(UA_NodeReferenceKind *refs, const UA_ExpandedNodeId *target,
- UA_UInt32 targetIdHash, UA_UInt32 targetNameHash) {
- UA_StatusCode retval = resizeReferenceTargets(refs, refs->refTargetsSize + 1);
- if(retval != UA_STATUSCODE_GOOD)
- return retval;
+ /* Insert into tree */
+ UA_ReferenceTargetTreeElem *entry = (UA_ReferenceTargetTreeElem*)
+ UA_malloc(sizeof(UA_ReferenceTargetTreeElem));
+ if(!entry)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
- UA_ReferenceTarget *entry = &refs->refTargets[refs->refTargetsSize];
- retval = UA_ExpandedNodeId_copy(target, &entry->targetId);
+ UA_StatusCode retval =
+ UA_NodePointer_copy(targetId, &entry->target.targetId);
if(retval != UA_STATUSCODE_GOOD) {
- if(refs->refTargetsSize== 0) {
- /* We had zero references before (realloc was a malloc) */
- UA_free(refs->refTargets);
- refs->refTargets = NULL;
- }
+ UA_free(entry);
return retval;
}
- entry->targetIdHash = targetIdHash;
- entry->targetNameHash = targetNameHash;
- unsigned char rank = ZIP_FFS32(UA_UInt32_random());
- ZIP_INSERT(UA_ReferenceTargetIdTree, &refs->refTargetsIdTree, entry, rank);
- ZIP_INSERT(UA_ReferenceTargetNameTree, &refs->refTargetsNameTree, entry, rank);
- refs->refTargetsSize++;
+ /* <-- The point of no return --> */
+
+ UA_ExpandedNodeId en = UA_NodePointer_toExpandedNodeId(targetId);
+ entry->targetIdHash = UA_ExpandedNodeId_hash(&en);
+ entry->target.targetNameHash = targetNameHash;
+
+ /* Insert to the id lookup binary search tree. Only the root is kept in refs
+ * to save space. */
+ struct aa_head _refIdTree = refIdTree;
+ _refIdTree.root = rk->targets.tree.idTreeRoot;
+ aa_insert(&_refIdTree, entry);
+ rk->targets.tree.idTreeRoot = _refIdTree.root;
+
+ /* Insert to the name lookup binary search tree */
+ struct aa_head _refNameTree = refNameTree;
+ _refNameTree.root = rk->targets.tree.nameTreeRoot;
+ aa_insert(&_refNameTree, entry);
+ rk->targets.tree.nameTreeRoot = _refNameTree.root;
+
+ rk->targetsSize++;
+
return UA_STATUSCODE_GOOD;
}
static UA_StatusCode
-addReferenceKind(UA_Node *node, const UA_AddReferencesItem *item,
- UA_UInt32 targetBrowseNameHash) {
+addReferenceKind(UA_NodeHead *head, UA_Byte refTypeIndex, UA_Boolean isForward,
+ const UA_NodePointer target, UA_UInt32 targetBrowseNameHash) {
UA_NodeReferenceKind *refs = (UA_NodeReferenceKind*)
- UA_realloc(node->references, sizeof(UA_NodeReferenceKind) * (node->referencesSize+1));
+ UA_realloc(head->references,
+ sizeof(UA_NodeReferenceKind) * (head->referencesSize+1));
if(!refs)
return UA_STATUSCODE_BADOUTOFMEMORY;
- node->references = refs;
+ head->references = refs;
- UA_StatusCode retval = UA_STATUSCODE_GOOD;
- UA_NodeReferenceKind *newRef = &refs[node->referencesSize];
+ UA_NodeReferenceKind *newRef = &refs[head->referencesSize];
memset(newRef, 0, sizeof(UA_NodeReferenceKind));
- ZIP_INIT(&newRef->refTargetsIdTree);
- ZIP_INIT(&newRef->refTargetsNameTree);
- newRef->isInverse = !item->isForward;
- retval |= UA_NodeId_copy(&item->referenceTypeId, &newRef->referenceTypeId);
- retval |= addReferenceTarget(newRef, &item->targetNodeId,
- UA_ExpandedNodeId_hash(&item->targetNodeId),
- targetBrowseNameHash);
+ newRef->referenceTypeIndex = refTypeIndex;
+ newRef->isInverse = !isForward;
+ UA_StatusCode retval =
+ addReferenceTarget(newRef, target, targetBrowseNameHash);
if(retval != UA_STATUSCODE_GOOD) {
- UA_NodeId_clear(&newRef->referenceTypeId);
- if(node->referencesSize == 0) {
- UA_free(node->references);
- node->references = NULL;
+ if(head->referencesSize == 0) {
+ UA_free(head->references);
+ head->references = NULL;
}
return retval;
}
- node->referencesSize++;
+ head->referencesSize++;
return UA_STATUSCODE_GOOD;
}
UA_StatusCode
-UA_Node_addReference(UA_Node *node, const UA_AddReferencesItem *item,
+UA_Node_addReference(UA_Node *node, UA_Byte refTypeIndex, UA_Boolean isForward,
+ const UA_ExpandedNodeId *targetNodeId,
UA_UInt32 targetBrowseNameHash) {
- /* Find the matching refkind */
- UA_NodeReferenceKind *existingRefs = NULL;
- for(size_t i = 0; i < node->referencesSize; ++i) {
- UA_NodeReferenceKind *refs = &node->references[i];
- if(refs->isInverse != item->isForward &&
- UA_NodeId_equal(&refs->referenceTypeId, &item->referenceTypeId)) {
- existingRefs = refs;
- break;
- }
- }
+ /* Find the matching reference kind */
+ for(size_t i = 0; i < node->head.referencesSize; ++i) {
+ UA_NodeReferenceKind *refs = &node->head.references[i];
+
+ /* Reference direction does not match */
+ if(refs->isInverse == isForward)
+ continue;
+
+ /* Reference type does not match */
+ if(refs->referenceTypeIndex != refTypeIndex)
+ continue;
- if(!existingRefs)
- return addReferenceKind(node, item, targetBrowseNameHash);
+ /* Does an identical reference already exist? */
+ const UA_ReferenceTarget *found =
+ UA_NodeReferenceKind_findTarget(refs, targetNodeId);
+ if(found)
+ return UA_STATUSCODE_BADDUPLICATEREFERENCENOTALLOWED;
- UA_ReferenceTarget tmpTarget;
- tmpTarget.targetId = item->targetNodeId;
- tmpTarget.targetIdHash = UA_ExpandedNodeId_hash(&item->targetNodeId);
- UA_ReferenceTarget *found =
- ZIP_FIND(UA_ReferenceTargetIdTree, &existingRefs->refTargetsIdTree, &tmpTarget);
- if(found)
- return UA_STATUSCODE_BADDUPLICATEREFERENCENOTALLOWED;
+ /* Add to existing ReferenceKind */
+ return addReferenceTarget(refs, UA_NodePointer_fromExpandedNodeId(targetNodeId),
+ targetBrowseNameHash);
+ }
+
+ /* Add new ReferenceKind for the target */
+ return addReferenceKind(&node->head, refTypeIndex, isForward,
+ UA_NodePointer_fromExpandedNodeId(targetNodeId),
+ targetBrowseNameHash);
- return addReferenceTarget(existingRefs, &item->targetNodeId,
- tmpTarget.targetIdHash, targetBrowseNameHash);
}
UA_StatusCode
-UA_Node_deleteReference(UA_Node *node, const UA_DeleteReferencesItem *item) {
- for(size_t i = node->referencesSize; i > 0; --i) {
- UA_NodeReferenceKind *refs = &node->references[i-1];
- if(item->isForward == refs->isInverse)
+UA_Node_deleteReference(UA_Node *node, UA_Byte refTypeIndex, UA_Boolean isForward,
+ const UA_ExpandedNodeId *targetNodeId) {
+ struct aa_head _refIdTree = refIdTree;
+ struct aa_head _refNameTree = refNameTree;
+
+ UA_NodeHead *head = &node->head;
+ for(size_t i = 0; i < head->referencesSize; i++) {
+ UA_NodeReferenceKind *refs = &head->references[i];
+ if(isForward == refs->isInverse)
continue;
- if(!UA_NodeId_equal(&item->referenceTypeId, &refs->referenceTypeId))
+ if(refTypeIndex != refs->referenceTypeIndex)
continue;
- for(size_t j = refs->refTargetsSize; j > 0; --j) {
- UA_ReferenceTarget *target = &refs->refTargets[j-1];
- if(!UA_NodeId_equal(&item->targetNodeId.nodeId, &target->targetId.nodeId))
- continue;
-
- /* Ok, delete the reference */
- ZIP_REMOVE(UA_ReferenceTargetIdTree, &refs->refTargetsIdTree, target);
- ZIP_REMOVE(UA_ReferenceTargetNameTree, &refs->refTargetsNameTree, target);
- UA_ExpandedNodeId_clear(&target->targetId);
- refs->refTargetsSize--;
-
- if(refs->refTargetsSize > 0) {
- /* At least one target remains in buffer */
- if(j-1 != refs->refTargetsSize) {
- /* Move last entry into the entry from where reference was removed */
- ZIP_REMOVE(UA_ReferenceTargetIdTree, &refs->refTargetsIdTree,
- &refs->refTargets[refs->refTargetsSize]);
- ZIP_REMOVE(UA_ReferenceTargetNameTree, &refs->refTargetsNameTree,
- &refs->refTargets[refs->refTargetsSize]);
- *target = refs->refTargets[refs->refTargetsSize];
- ZIP_INSERT(UA_ReferenceTargetIdTree, &refs->refTargetsIdTree,
- target, ZIP_RANK(target, idTreeFields));
- ZIP_INSERT(UA_ReferenceTargetNameTree, &refs->refTargetsNameTree,
- target, ZIP_RANK(target, nameTreeFields));
- }
- /* Shrink down allocated buffer, ignore failure */
- (void)resizeReferenceTargets(refs, refs->refTargetsSize);
- return UA_STATUSCODE_GOOD;
- }
+ /* Cast out the const qualifier (hack!) */
+ UA_ReferenceTarget *target = (UA_ReferenceTarget*)(uintptr_t)
+ UA_NodeReferenceKind_findTarget(refs, targetNodeId);
+ if(!target)
+ continue;
- /* No target for the ReferenceType remaining. Remove entry. */
- UA_free(refs->refTargets);
- UA_NodeId_clear(&refs->referenceTypeId);
- node->referencesSize--;
- if(node->referencesSize > 0) {
- if(i-1 != node->referencesSize) {
- /* Move last array node into array node from where reference kind was removed */
- node->references[i-1] = node->references[node->referencesSize];
- }
- /* And shrink down allocated buffer for one entry */
- UA_NodeReferenceKind *newRefs = (UA_NodeReferenceKind*)
- UA_realloc(node->references, sizeof(UA_NodeReferenceKind) * node->referencesSize);
- /* Ignore errors in case memory buffer could not be shrinked down */
- if(newRefs) {
- node->references = newRefs;
- }
- return UA_STATUSCODE_GOOD;
+ /* Ok, delete the reference. Cannot fail */
+ refs->targetsSize--;
+
+ if(!refs->hasRefTree) {
+ /* Remove from array */
+ UA_NodePointer_clear(&target->targetId);
+
+ /* Elements remaining. Realloc. */
+ if(refs->targetsSize > 0) {
+ if(target != &refs->targets.array[refs->targetsSize])
+ *target = refs->targets.array[refs->targetsSize];
+ UA_ReferenceTarget *newRefs = (UA_ReferenceTarget*)
+ UA_realloc(refs->targets.array,
+ sizeof(UA_ReferenceTarget) * refs->targetsSize);
+ if(newRefs)
+ refs->targets.array = newRefs;
+ return UA_STATUSCODE_GOOD; /* Realloc allowed to fail */
}
+ /* Remove the last target. Remove the ReferenceKind below */
+ UA_free(refs->targets.array);
+ } else {
+ /* Remove from the tree */
+ _refIdTree.root = refs->targets.tree.idTreeRoot;
+ aa_remove(&_refIdTree, target);
+ refs->targets.tree.idTreeRoot = _refIdTree.root;
+
+ _refNameTree.root = refs->targets.tree.nameTreeRoot;
+ aa_remove(&_refNameTree, target);
+ refs->targets.tree.nameTreeRoot = _refNameTree.root;
+
+ UA_NodePointer_clear(&target->targetId);
+ UA_free(target);
+ if(refs->targets.tree.idTreeRoot)
+ return UA_STATUSCODE_GOOD; /* At least one target remains */
+ }
+
+ /* No targets remaining. Remove the ReferenceKind. */
+ head->referencesSize--;
+ if(head->referencesSize > 0) {
+ /* No target for the ReferenceType remaining. Remove and shrink down
+ * allocated buffer. Ignore errors in case memory buffer could not
+ * be shrinked down. */
+ if(i != head->referencesSize)
+ head->references[i] = head->references[node->head.referencesSize];
+ UA_NodeReferenceKind *newRefs = (UA_NodeReferenceKind*)
+ UA_realloc(head->references,
+ sizeof(UA_NodeReferenceKind) * head->referencesSize);
+ if(newRefs)
+ head->references = newRefs;
+ } else {
/* No remaining references of any ReferenceType */
- UA_free(node->references);
- node->references = NULL;
- return UA_STATUSCODE_GOOD;
+ UA_free(head->references);
+ head->references = NULL;
}
+ return UA_STATUSCODE_GOOD;
}
return UA_STATUSCODE_UNCERTAINREFERENCENOTDELETED;
}
void
-UA_Node_deleteReferencesSubset(UA_Node *node, size_t referencesSkipSize,
- UA_NodeId* referencesSkip) {
- /* Nothing to do */
- if(node->referencesSize == 0 || node->references == NULL)
- return;
-
- for(size_t i = node->referencesSize; i > 0; --i) {
- UA_NodeReferenceKind *refs = &node->references[i-1];
+UA_Node_deleteReferencesSubset(UA_Node *node, const UA_ReferenceTypeSet *keepSet) {
+ UA_NodeHead *head = &node->head;
+ struct aa_head _refIdTree = refIdTree;
+ for(size_t i = 0; i < head->referencesSize; i++) {
+ /* Keep the references of this type? */
+ UA_NodeReferenceKind *refs = &head->references[i];
+ if(UA_ReferenceTypeSet_contains(keepSet, refs->referenceTypeIndex))
+ continue;
- /* Shall we keep the references of this type? */
- UA_Boolean skip = false;
- for(size_t j = 0; j < referencesSkipSize; j++) {
- if(UA_NodeId_equal(&refs->referenceTypeId, &referencesSkip[j])) {
- skip = true;
- break;
+ /* Remove all target entries. Don't remove entries from browseName tree.
+ * The entire ReferenceKind will be removed anyway. */
+ if(!refs->hasRefTree) {
+ for(size_t j = 0; j < refs->targetsSize; j++)
+ UA_NodePointer_clear(&refs->targets.array[j].targetId);
+ UA_free(refs->targets.array);
+ } else {
+ _refIdTree.root = refs->targets.tree.idTreeRoot;
+ while(_refIdTree.root) {
+ UA_ReferenceTargetTreeElem *elem = (UA_ReferenceTargetTreeElem*)
+ ((uintptr_t)_refIdTree.root -
+ offsetof(UA_ReferenceTargetTreeElem, idTreeEntry));
+ aa_remove(&_refIdTree, elem);
+ UA_NodePointer_clear(&elem->target.targetId);
+ UA_free(elem);
}
}
- if(skip)
- continue;
- /* Remove references */
- for(size_t j = 0; j < refs->refTargetsSize; j++)
- UA_ExpandedNodeId_clear(&refs->refTargets[j].targetId);
- UA_free(refs->refTargets);
- UA_NodeId_clear(&refs->referenceTypeId);
- node->referencesSize--;
-
- /* Move last references-kind entry to this position */
- if(i-1 == node->referencesSize) /* Don't memcpy over the same position */
- continue;
- node->references[i-1] = node->references[node->referencesSize];
+ /* Move last references-kind entry to this position. Don't memcpy over
+ * the same position. Decrease i to repeat at this location. */
+ head->referencesSize--;
+ if(i != head->referencesSize) {
+ head->references[i] = head->references[head->referencesSize];
+ i--;
+ }
}
- if(node->referencesSize > 0) {
- /* Realloc to save memory */
+ if(head->referencesSize > 0) {
+ /* Realloc to save memory. Ignore if realloc fails. */
UA_NodeReferenceKind *refs = (UA_NodeReferenceKind*)
- UA_realloc(node->references, sizeof(UA_NodeReferenceKind) * node->referencesSize);
- if(refs) /* Do nothing if realloc fails */
- node->references = refs;
- return;
+ UA_realloc(head->references,
+ sizeof(UA_NodeReferenceKind) * head->referencesSize);
+ if(refs)
+ head->references = refs;
+ } else {
+ /* The array is empty. Remove. */
+ UA_free(head->references);
+ head->references = NULL;
}
-
- /* The array is empty. Remove. */
- UA_free(node->references);
- node->references = NULL;
}
void UA_Node_deleteReferences(UA_Node *node) {
- UA_Node_deleteReferencesSubset(node, 0, NULL);
+ UA_ReferenceTypeSet noRefs;
+ UA_ReferenceTypeSet_init(&noRefs);
+ UA_Node_deleteReferencesSubset(node, &noRefs);
}
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/src/server/ua_server.c" ***********************************/
+/**** amalgamated original file "/src/server/ua_server.c" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -22820,12 +21554,15 @@ void UA_Node_deleteReferences(UA_Node *node) {
* Copyright 2017 (c) Mark Giraud, Fraunhofer IOSB
* Copyright 2018 (c) Hilscher Gesellschaft für Systemautomation mbH (Author: Martin Lang)
* Copyright 2019 (c) Kalycito Infotech Private Limited
+ * Copyright 2021 (c) Fraunhofer IOSB (Author: Jan Hermes)
+ * Copyright 2022 (c) Fraunhofer IOSB (Author: Andreas Ebner)
*/
#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL
#endif
+
#ifdef UA_ENABLE_SUBSCRIPTIONS
#endif
@@ -22845,7 +21582,7 @@ void UA_Node_deleteReferences(UA_Node *node) {
* Application URI.
*
* This is done as soon as the Namespace Array is read or written via node value
- * read / write services, or UA_Server_addNamespace,
+ * read / write services, or UA_Server_addNamespace, or UA_Server_getNamespaceByIndex
* UA_Server_getNamespaceByName or UA_Server_run_startup is called.
*
* Therefore one has to set the custom NS1 URI before one of the previously
@@ -22871,14 +21608,13 @@ UA_UInt16 addNamespace(UA_Server *server, const UA_String name) {
/* Make the array bigger */
UA_String *newNS = (UA_String*)UA_realloc(server->namespaces,
sizeof(UA_String) * (server->namespacesSize + 1));
- if(!newNS)
- return 0;
+ UA_CHECK_MEM(newNS, return 0);
+
server->namespaces = newNS;
/* Copy the namespace string */
UA_StatusCode retval = UA_String_copy(&name, &server->namespaces[server->namespacesSize]);
- if(retval != UA_STATUSCODE_GOOD)
- return 0;
+ UA_CHECK_STATUS(retval, return 0);
/* Announce the change (otherwise, the array appears unchanged) */
++server->namespacesSize;
@@ -22890,17 +21626,16 @@ UA_UInt16 UA_Server_addNamespace(UA_Server *server, const char* name) {
UA_String nameString;
nameString.length = strlen(name);
nameString.data = (UA_Byte*)(uintptr_t)name;
- UA_LOCK(server->serviceMutex);
+ UA_LOCK(&server->serviceMutex);
UA_UInt16 retVal = addNamespace(server, nameString);
- UA_UNLOCK(server->serviceMutex);
+ UA_UNLOCK(&server->serviceMutex);
return retVal;
}
UA_ServerConfig*
UA_Server_getConfig(UA_Server *server) {
- if(!server)
- return NULL;
- return &server->config;
+ UA_CHECK_MEM(server, return NULL);
+ return &server->config;
}
UA_StatusCode
@@ -22920,88 +21655,97 @@ getNamespaceByName(UA_Server *server, const UA_String namespaceUri,
}
UA_StatusCode
+getNamespaceByIndex(UA_Server *server, const size_t namespaceIndex,
+ UA_String *foundUri) {
+ /* ensure that the uri for ns1 is set up from the app description */
+ setupNs1Uri(server);
+ UA_StatusCode res = UA_STATUSCODE_BADNOTFOUND;
+ if(namespaceIndex > server->namespacesSize)
+ return res;
+ res = UA_String_copy(&server->namespaces[namespaceIndex], foundUri);
+ return res;
+}
+
+UA_StatusCode
UA_Server_getNamespaceByName(UA_Server *server, const UA_String namespaceUri,
size_t *foundIndex) {
- UA_LOCK(server->serviceMutex);
+ UA_LOCK(&server->serviceMutex);
UA_StatusCode res = getNamespaceByName(server, namespaceUri, foundIndex);
- UA_UNLOCK(server->serviceMutex);
+ UA_UNLOCK(&server->serviceMutex);
+ return res;
+}
+
+UA_StatusCode
+UA_Server_getNamespaceByIndex(UA_Server *server, const size_t namespaceIndex,
+ UA_String *foundUri) {
+ UA_LOCK(&server->serviceMutex);
+ UA_StatusCode res = getNamespaceByIndex(server, namespaceIndex, foundUri);
+ UA_UNLOCK(&server->serviceMutex);
return res;
}
UA_StatusCode
UA_Server_forEachChildNodeCall(UA_Server *server, UA_NodeId parentNodeId,
UA_NodeIteratorCallback callback, void *handle) {
- UA_LOCK(server->serviceMutex);
- const UA_Node *parent = UA_NODESTORE_GET(server, &parentNodeId);
- if(!parent) {
- UA_UNLOCK(server->serviceMutex);
- return UA_STATUSCODE_BADNODEIDINVALID;
- }
+ UA_BrowseDescription bd;
+ UA_BrowseDescription_init(&bd);
+ bd.nodeId = parentNodeId;
+ bd.browseDirection = UA_BROWSEDIRECTION_BOTH;
+ bd.resultMask = UA_BROWSERESULTMASK_REFERENCETYPEID | UA_BROWSERESULTMASK_ISFORWARD;
- /* TODO: We need to do an ugly copy of the references array since users may
- * delete references from within the callback. In single-threaded mode this
- * changes the same node we point at here. In multi-threaded mode, this
- * creates a new copy as nodes are truly immutable.
- * The callback could remove a node via the regular public API.
- * This can remove a member of the nodes-array we iterate over...
- * */
- UA_Node *parentCopy = UA_Node_copy_alloc(parent);
- if(!parentCopy) {
- UA_NODESTORE_RELEASE(server, parent);
- UA_UNLOCK(server->serviceMutex);
- return UA_STATUSCODE_BADUNEXPECTEDERROR;
- }
+ UA_BrowseResult br = UA_Server_browse(server, 0, &bd);
+ UA_StatusCode res = br.statusCode;
+ UA_CHECK_STATUS(res, goto cleanup);
- UA_StatusCode retval = UA_STATUSCODE_GOOD;
- for(size_t i = parentCopy->referencesSize; i > 0; --i) {
- UA_NodeReferenceKind *ref = &parentCopy->references[i - 1];
- for(size_t j = 0; j<ref->refTargetsSize; j++) {
- UA_UNLOCK(server->serviceMutex);
- retval = callback(ref->refTargets[j].targetId.nodeId, ref->isInverse,
- ref->referenceTypeId, handle);
- UA_LOCK(server->serviceMutex);
- if(retval != UA_STATUSCODE_GOOD)
- goto cleanup;
- }
+ for(size_t i = 0; i < br.referencesSize; i++) {
+ if(!UA_ExpandedNodeId_isLocal(&br.references[i].nodeId))
+ continue;
+ res = callback(br.references[i].nodeId.nodeId, !br.references[i].isForward,
+ br.references[i].referenceTypeId, handle);
+ UA_CHECK_STATUS(res, goto cleanup);
}
-
cleanup:
- UA_Node_clear(parentCopy);
- UA_free(parentCopy);
-
- UA_NODESTORE_RELEASE(server, parent);
- UA_UNLOCK(server->serviceMutex);
- return retval;
+ UA_BrowseResult_clear(&br);
+ return res;
}
/********************/
/* Server Lifecycle */
/********************/
+static void
+serverExecuteRepeatedCallback(UA_Server *server, UA_ApplicationCallback cb,
+ void *callbackApplication, void *data);
+
/* The server needs to be stopped before it can be deleted */
void UA_Server_delete(UA_Server *server) {
- /* Delete all internal data */
+ UA_LOCK(&server->serviceMutex);
+
UA_Server_deleteSecureChannels(server);
- UA_LOCK(server->serviceMutex);
session_list_entry *current, *temp;
LIST_FOREACH_SAFE(current, &server->sessions, pointers, temp) {
UA_Server_removeSession(server, current, UA_DIAGNOSTICEVENT_CLOSE);
}
- UA_UNLOCK(server->serviceMutex);
UA_Array_delete(server->namespaces, server->namespacesSize, &UA_TYPES[UA_TYPES_STRING]);
#ifdef UA_ENABLE_SUBSCRIPTIONS
UA_MonitoredItem *mon, *mon_tmp;
LIST_FOREACH_SAFE(mon, &server->localMonitoredItems, listEntry, mon_tmp) {
LIST_REMOVE(mon, listEntry);
- UA_LOCK(server->serviceMutex);
UA_MonitoredItem_delete(server, mon);
- UA_UNLOCK(server->serviceMutex);
}
+ /* Remove subscriptions without a session */
+ UA_Subscription *sub, *sub_tmp;
+ LIST_FOREACH_SAFE(sub, &server->subscriptions, serverListEntry, sub_tmp) {
+ UA_Subscription_delete(server, sub);
+ }
+ UA_assert(server->monitoredItemsSize == 0);
+ UA_assert(server->subscriptionsSize == 0);
+
#ifdef UA_ENABLE_SUBSCRIPTIONS_ALARMS_CONDITIONS
UA_ConditionList_delete(server);
-#endif//UA_ENABLE_ALARMS_CONDITIONS
+#endif
#endif
@@ -23010,7 +21754,7 @@ void UA_Server_delete(UA_Server *server) {
#endif
#ifdef UA_ENABLE_DISCOVERY
- UA_DiscoveryManager_deleteMembers(&server->discoveryManager, server);
+ UA_DiscoveryManager_clear(&server->discoveryManager, server);
#endif
#if UA_MULTITHREADING >= 100
@@ -23018,22 +21762,21 @@ void UA_Server_delete(UA_Server *server) {
#endif
/* Clean up the Admin Session */
- UA_LOCK(server->serviceMutex);
- UA_Session_deleteMembersCleanup(&server->adminSession, server);
- UA_UNLOCK(server->serviceMutex);
+ UA_Session_clear(&server->adminSession, server);
- /* Clean up the work queue */
- UA_WorkQueue_cleanup(&server->workQueue);
+ UA_UNLOCK(&server->serviceMutex); /* The timer has its own mutex */
- /* Delete the timed work */
- UA_Timer_deleteMembers(&server->timer);
+ /* Execute all remaining delayed events and clean up the timer */
+ UA_Timer_process(&server->timer, UA_DateTime_nowMonotonic() + 1,
+ (UA_TimerExecutionCallback)serverExecuteRepeatedCallback, server);
+ UA_Timer_clear(&server->timer);
/* Clean up the config */
UA_ServerConfig_clean(&server->config);
#if UA_MULTITHREADING >= 100
- UA_LOCK_DESTROY(server->networkMutex)
- UA_LOCK_DESTROY(server->serviceMutex)
+ UA_LOCK_DESTROY(&server->networkMutex);
+ UA_LOCK_DESTROY(&server->serviceMutex);
#endif
/* Delete the server itself */
@@ -23043,29 +21786,34 @@ void UA_Server_delete(UA_Server *server) {
/* Recurring cleanup. Removing unused and timed-out channels and sessions */
static void
UA_Server_cleanup(UA_Server *server, void *_) {
- UA_LOCK(server->serviceMutex);
+ UA_LOCK(&server->serviceMutex);
UA_DateTime nowMonotonic = UA_DateTime_nowMonotonic();
UA_Server_cleanupSessions(server, nowMonotonic);
UA_Server_cleanupTimedOutSecureChannels(server, nowMonotonic);
#ifdef UA_ENABLE_DISCOVERY
UA_Discovery_cleanupTimedOut(server, nowMonotonic);
#endif
- UA_UNLOCK(server->serviceMutex);
+ UA_UNLOCK(&server->serviceMutex);
}
/********************/
/* Server Lifecycle */
/********************/
+static
+UA_INLINE
+UA_Boolean UA_Server_NodestoreIsConfigured(UA_Server *server) {
+ return server->config.nodestore.getNode != NULL;
+}
+
static UA_Server *
UA_Server_init(UA_Server *server) {
+
UA_StatusCode res = UA_STATUSCODE_GOOD;
-
- if(!server->config.nodestore.getNode) {
- UA_LOG_FATAL(&server->config.logger, UA_LOGCATEGORY_SERVER,
- "No Nodestore configured in the server");
- goto cleanup;
- }
+ UA_CHECK_FATAL(UA_Server_NodestoreIsConfigured(server), goto cleanup,
+ &server->config.logger, UA_LOGCATEGORY_SERVER,
+ "No Nodestore configured in the server"
+ );
/* Init start time to zero, the actual start time will be sampled in
* UA_Server_run_startup() */
@@ -23077,28 +21825,25 @@ UA_Server_init(UA_Server *server) {
#endif
#if UA_MULTITHREADING >= 100
- UA_LOCK_INIT(server->networkMutex)
- UA_LOCK_INIT(server->serviceMutex)
+ UA_LOCK_INIT(&server->networkMutex);
+ UA_LOCK_INIT(&server->serviceMutex);
#endif
/* Initialize the handling of repeated callbacks */
UA_Timer_init(&server->timer);
- UA_WorkQueue_init(&server->workQueue);
-
/* Initialize the adminSession */
UA_Session_init(&server->adminSession);
server->adminSession.sessionId.identifierType = UA_NODEIDTYPE_GUID;
server->adminSession.sessionId.identifier.guid.data1 = 1;
server->adminSession.validTill = UA_INT64_MAX;
+ server->adminSession.sessionName = UA_STRING_ALLOC("Administrator");
/* Create Namespaces 0 and 1
* Ns1 will be filled later with the uri from the app description */
server->namespaces = (UA_String *)UA_Array_new(2, &UA_TYPES[UA_TYPES_STRING]);
- if(!server->namespaces) {
- UA_Server_delete(server);
- return NULL;
- }
+ UA_CHECK_MEM(server->namespaces, goto cleanup);
+
server->namespaces[0] = UA_STRING_ALLOC("http://opcfoundation.org/UA/");
server->namespaces[1] = UA_STRING_NULL;
server->namespacesSize = 2;
@@ -23123,14 +21868,20 @@ UA_Server_init(UA_Server *server) {
/* Initialize namespace 0*/
res = UA_Server_initNS0(server);
- if(res != UA_STATUSCODE_GOOD)
- goto cleanup;
+ UA_CHECK_STATUS(res, goto cleanup);
+#ifdef UA_ENABLE_PUBSUB
/* Build PubSub information model */
#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL
UA_Server_initPubSubNS0(server);
#endif
+#ifdef UA_ENABLE_PUBSUB_MONITORING
+ /* setup default PubSub monitoring callbacks */
+ res = UA_PubSubManager_setDefaultMonitoringCallbacks(&server->config.pubSubConfig.monitoringInterface);
+ UA_CHECK_STATUS(res, goto cleanup);
+#endif /* UA_ENABLE_PUBSUB_MONITORING */
+#endif /* UA_ENABLE_PUBSUB */
return server;
cleanup:
@@ -23139,13 +21890,20 @@ UA_Server_init(UA_Server *server) {
}
UA_Server *
-UA_Server_newWithConfig(const UA_ServerConfig *config) {
- if(!config)
- return NULL;
+UA_Server_newWithConfig(UA_ServerConfig *config) {
+ UA_CHECK_MEM(config, return NULL);
+
UA_Server *server = (UA_Server *)UA_calloc(1, sizeof(UA_Server));
- if(!server)
- return NULL;
+ UA_CHECK_MEM(server, UA_ServerConfig_clean(config); return NULL);
+
server->config = *config;
+ /* The config might have been "moved" into the server struct. Ensure that
+ * the logger pointer is correct. */
+ for(size_t i = 0; i < server->config.securityPoliciesSize; i++)
+ server->config.securityPolicies[i].logger = &server->config.logger;
+
+ /* Reset the old config */
+ memset(config, 0, sizeof(UA_ServerConfig));
return UA_Server_init(server);
}
@@ -23169,11 +21927,12 @@ setServerShutdown(UA_Server *server) {
UA_StatusCode
UA_Server_addTimedCallback(UA_Server *server, UA_ServerCallback callback,
void *data, UA_DateTime date, UA_UInt64 *callbackId) {
- UA_LOCK(server->serviceMutex);
- UA_StatusCode retval = UA_Timer_addTimedCallback(&server->timer,
- (UA_ApplicationCallback)callback,
- server, data, date, callbackId);
- UA_UNLOCK(server->serviceMutex);
+ UA_LOCK(&server->serviceMutex);
+ UA_StatusCode retval =
+ UA_Timer_addTimedCallback(&server->timer,
+ (UA_ApplicationCallback)callback,
+ server, data, date, callbackId);
+ UA_UNLOCK(&server->serviceMutex);
return retval;
}
@@ -23183,32 +21942,35 @@ addRepeatedCallback(UA_Server *server, UA_ServerCallback callback,
UA_UInt64 *callbackId) {
return UA_Timer_addRepeatedCallback(&server->timer,
(UA_ApplicationCallback)callback,
- server, data, interval_ms, callbackId);
+ server, data, interval_ms, NULL,
+ UA_TIMER_HANDLE_CYCLEMISS_WITH_CURRENTTIME, callbackId);
}
UA_StatusCode
UA_Server_addRepeatedCallback(UA_Server *server, UA_ServerCallback callback,
void *data, UA_Double interval_ms,
UA_UInt64 *callbackId) {
- UA_LOCK(server->serviceMutex);
- UA_StatusCode retval = addRepeatedCallback(server, callback, data, interval_ms, callbackId);
- UA_UNLOCK(server->serviceMutex);
+ UA_LOCK(&server->serviceMutex);
+ UA_StatusCode retval =
+ addRepeatedCallback(server, callback, data, interval_ms, callbackId);
+ UA_UNLOCK(&server->serviceMutex);
return retval;
}
UA_StatusCode
changeRepeatedCallbackInterval(UA_Server *server, UA_UInt64 callbackId,
- UA_Double interval_ms) {
- return UA_Timer_changeRepeatedCallbackInterval(&server->timer, callbackId,
- interval_ms);
+ UA_Double interval_ms) {
+ return UA_Timer_changeRepeatedCallback(&server->timer, callbackId,
+ interval_ms, NULL, UA_TIMER_HANDLE_CYCLEMISS_WITH_CURRENTTIME);
}
UA_StatusCode
UA_Server_changeRepeatedCallbackInterval(UA_Server *server, UA_UInt64 callbackId,
UA_Double interval_ms) {
- UA_LOCK(server->serviceMutex);
- UA_StatusCode retval = changeRepeatedCallbackInterval(server, callbackId, interval_ms);
- UA_UNLOCK(server->serviceMutex);
+ UA_LOCK(&server->serviceMutex);
+ UA_StatusCode retval =
+ changeRepeatedCallbackInterval(server, callbackId, interval_ms);
+ UA_UNLOCK(&server->serviceMutex);
return retval;
}
@@ -23219,9 +21981,9 @@ removeCallback(UA_Server *server, UA_UInt64 callbackId) {
void
UA_Server_removeCallback(UA_Server *server, UA_UInt64 callbackId) {
- UA_LOCK(server->serviceMutex);
+ UA_LOCK(&server->serviceMutex);
removeCallback(server, callbackId);
- UA_UNLOCK(server->serviceMutex);
+ UA_UNLOCK(&server->serviceMutex);
}
UA_StatusCode
@@ -23232,18 +21994,18 @@ UA_Server_updateCertificate(UA_Server *server,
UA_Boolean closeSessions,
UA_Boolean closeSecureChannels) {
- if(!server || !oldCertificate || !newCertificate || !newPrivateKey)
- return UA_STATUSCODE_BADINTERNALERROR;
+ UA_CHECK(server && oldCertificate && newCertificate && newPrivateKey,
+ return UA_STATUSCODE_BADINTERNALERROR);
if(closeSessions) {
session_list_entry *current;
LIST_FOREACH(current, &server->sessions, pointers) {
if(UA_ByteString_equal(oldCertificate,
&current->session.header.channel->securityPolicy->localCertificate)) {
- UA_LOCK(server->serviceMutex);
+ UA_LOCK(&server->serviceMutex);
UA_Server_removeSessionByToken(server, &current->session.header.authenticationToken,
UA_DIAGNOSTICEVENT_CLOSE);
- UA_UNLOCK(server->serviceMutex);
+ UA_UNLOCK(&server->serviceMutex);
}
}
@@ -23261,11 +22023,11 @@ UA_Server_updateCertificate(UA_Server *server,
while(i < server->config.endpointsSize) {
UA_EndpointDescription *ed = &server->config.endpoints[i];
if(UA_ByteString_equal(&ed->serverCertificate, oldCertificate)) {
- UA_String_deleteMembers(&ed->serverCertificate);
+ UA_String_clear(&ed->serverCertificate);
UA_String_copy(newCertificate, &ed->serverCertificate);
- UA_SecurityPolicy *sp = UA_SecurityPolicy_getSecurityPolicyByUri(server, &server->config.endpoints[i].securityPolicyUri);
- if(!sp)
- return UA_STATUSCODE_BADINTERNALERROR;
+ UA_SecurityPolicy *sp = getSecurityPolicyByUri(server,
+ &server->config.endpoints[i].securityPolicyUri);
+ UA_CHECK_MEM(sp, return UA_STATUSCODE_BADINTERNALERROR);
sp->updateCertificateAndPrivateKey(sp, *newCertificate, *newPrivateKey);
}
i++;
@@ -23279,8 +22041,7 @@ UA_Server_updateCertificate(UA_Server *server,
/***************************/
UA_SecurityPolicy *
-UA_SecurityPolicy_getSecurityPolicyByUri(const UA_Server *server,
- const UA_ByteString *securityPolicyUri) {
+getSecurityPolicyByUri(const UA_Server *server, const UA_ByteString *securityPolicyUri) {
for(size_t i = 0; i < server->config.securityPoliciesSize; i++) {
UA_SecurityPolicy *securityPolicyCandidate = &server->config.securityPolicies[i];
if(UA_ByteString_equal(securityPolicyUri, &securityPolicyCandidate->policyUri))
@@ -23294,27 +22055,47 @@ UA_SecurityPolicy_getSecurityPolicyByUri(const UA_Server *server,
* SecurityPolicies */
static UA_StatusCode
verifyServerApplicationURI(const UA_Server *server) {
+ const UA_String securityPolicyNoneUri = UA_STRING("http://opcfoundation.org/UA/SecurityPolicy#None");
for(size_t i = 0; i < server->config.securityPoliciesSize; i++) {
UA_SecurityPolicy *sp = &server->config.securityPolicies[i];
+ if(UA_String_equal(&sp->policyUri, &securityPolicyNoneUri) && (sp->localCertificate.length == 0))
+ continue;
UA_StatusCode retval = server->config.certificateVerification.
verifyApplicationURI(server->config.certificateVerification.context,
&sp->localCertificate,
&server->config.applicationDescription.applicationUri);
- if(retval != UA_STATUSCODE_GOOD) {
- UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
- "The configured ApplicationURI does not match the URI "
- "specified in the certificate for the SecurityPolicy %.*s",
- (int)sp->policyUri.length, sp->policyUri.data);
- return retval;
- }
+
+ UA_CHECK_STATUS_ERROR(retval, return retval, &server->config.logger, UA_LOGCATEGORY_SERVER,
+ "The configured ApplicationURI \"%.*s\"does not match the "
+ "ApplicationURI specified in the certificate for the "
+ "SecurityPolicy %.*s",
+ (int)server->config.applicationDescription.applicationUri.length,
+ server->config.applicationDescription.applicationUri.data,
+ (int)sp->policyUri.length, sp->policyUri.data);
}
return UA_STATUSCODE_GOOD;
}
#endif
-UA_ServerStatistics UA_Server_getStatistics(UA_Server *server)
-{
- return server->serverStats;
+UA_ServerStatistics
+UA_Server_getStatistics(UA_Server *server) {
+ UA_ServerStatistics stat;
+ stat.ns = server->networkStatistics;
+ stat.scs = server->secureChannelStatistics;
+
+ stat.ss.currentSessionCount = server->activeSessionCount;
+ stat.ss.cumulatedSessionCount =
+ server->serverDiagnosticsSummary.cumulatedSessionCount;
+ stat.ss.securityRejectedSessionCount =
+ server->serverDiagnosticsSummary.securityRejectedSessionCount;
+ stat.ss.rejectedSessionCount =
+ server->serverDiagnosticsSummary.rejectedSessionCount;
+ stat.ss.sessionTimeoutCount =
+ server->serverDiagnosticsSummary.sessionTimeoutCount;
+ stat.ss.sessionAbortCount =
+ server->serverDiagnosticsSummary.sessionAbortCount;
+
+ return stat;
}
/********************/
@@ -23338,18 +22119,19 @@ UA_Server_run_startup(UA_Server *server) {
* E.g. if fuzzing is enabled, and two clients are connected, subscriptions do not work properly,
* since the tokens will be overridden to allow easier fuzzing. */
UA_LOG_FATAL(&server->config.logger, UA_LOGCATEGORY_SERVER,
- "Server was built with unsafe fuzzing mode. This should only be used for specific fuzzing builds.");
+ "Server was built with unsafe fuzzing mode. "
+ "This should only be used for specific fuzzing builds.");
#endif
/* ensure that the uri for ns1 is set up from the app description */
setupNs1Uri(server);
/* write ServerArray with same ApplicationURI value as NamespaceArray */
- UA_StatusCode retVal = writeNs0VariableArray(server, UA_NS0ID_SERVER_SERVERARRAY,
- &server->config.applicationDescription.applicationUri,
- 1, &UA_TYPES[UA_TYPES_STRING]);
- if(retVal != UA_STATUSCODE_GOOD)
- return retVal;
+ UA_StatusCode retVal =
+ writeNs0VariableArray(server, UA_NS0ID_SERVER_SERVERARRAY,
+ &server->config.applicationDescription.applicationUri,
+ 1, &UA_TYPES[UA_TYPES_STRING]);
+ UA_CHECK_STATUS(retVal, return retVal);
if(server->state > UA_SERVERLIFECYCLE_FRESH)
return UA_STATUSCODE_GOOD;
@@ -23368,8 +22150,7 @@ UA_Server_run_startup(UA_Server *server) {
/* Does the ApplicationURI match the local certificates? */
#ifdef UA_ENABLE_ENCRYPTION
retVal = verifyServerApplicationURI(server);
- if(retVal != UA_STATUSCODE_GOOD)
- return retVal;
+ UA_CHECK_STATUS(retVal, return retVal);
#endif
/* Sample the start time and set it to the Server object */
@@ -23385,12 +22166,14 @@ UA_Server_run_startup(UA_Server *server) {
UA_StatusCode result = UA_STATUSCODE_GOOD;
for(size_t i = 0; i < server->config.networkLayersSize; ++i) {
UA_ServerNetworkLayer *nl = &server->config.networkLayers[i];
- nl->statistics = &server->serverStats.ns;
- result |= nl->start(nl, &server->config.customHostname);
+ nl->statistics = &server->networkStatistics;
+ result |= nl->start(nl, &server->config.logger, &server->config.customHostname);
}
+ UA_CHECK_STATUS(result, return result);
- /* Update the application description to match the previously added discovery urls.
- * We can only do this after the network layer is started since it inits the discovery url */
+ /* Update the application description to match the previously added
+ * discovery urls. We can only do this after the network layer is started
+ * since it inits the discovery url */
if(server->config.applicationDescription.discoveryUrlsSize != 0) {
UA_Array_delete(server->config.applicationDescription.discoveryUrls,
server->config.applicationDescription.discoveryUrlsSize,
@@ -23399,27 +22182,30 @@ UA_Server_run_startup(UA_Server *server) {
}
server->config.applicationDescription.discoveryUrls = (UA_String *)
UA_Array_new(server->config.networkLayersSize, &UA_TYPES[UA_TYPES_STRING]);
- if(!server->config.applicationDescription.discoveryUrls)
- return UA_STATUSCODE_BADOUTOFMEMORY;
- server->config.applicationDescription.discoveryUrlsSize = server->config.networkLayersSize;
+ UA_CHECK_MEM(server->config.applicationDescription.discoveryUrls,
+ return UA_STATUSCODE_BADOUTOFMEMORY);
+
+ server->config.applicationDescription.discoveryUrlsSize =
+ server->config.networkLayersSize;
for(size_t i = 0; i < server->config.applicationDescription.discoveryUrlsSize; i++) {
UA_ServerNetworkLayer *nl = &server->config.networkLayers[i];
- UA_String_copy(&nl->discoveryUrl, &server->config.applicationDescription.discoveryUrls[i]);
+ UA_String_copy(&nl->discoveryUrl,
+ &server->config.applicationDescription.discoveryUrls[i]);
}
- /* Spin up the worker threads */
-#if UA_MULTITHREADING >= 200
- UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_SERVER,
- "Spinning up %" PRIu16 " worker thread(s)", server->config.nThreads);
- UA_WorkQueue_start(&server->workQueue, server->config.nThreads);
-#endif
-
/* Start the multicast discovery server */
#ifdef UA_ENABLE_DISCOVERY_MULTICAST
- if(server->config.discovery.mdnsEnable)
+ if(server->config.mdnsEnabled)
startMulticastDiscoveryServer(server);
#endif
+ /* Update Endpoint description */
+ for(size_t i = 0; i < server->config.endpointsSize; ++i){
+ UA_ApplicationDescription_clear(&server->config.endpoints[i].server);
+ UA_ApplicationDescription_copy(&server->config.applicationDescription,
+ &server->config.endpoints[i].server);
+ }
+
server->state = UA_SERVERLIFECYCLE_FRESH;
return result;
@@ -23427,12 +22213,12 @@ UA_Server_run_startup(UA_Server *server) {
static void
serverExecuteRepeatedCallback(UA_Server *server, UA_ApplicationCallback cb,
- void *callbackApplication, void *data) {
-#if UA_MULTITHREADING >= 200
- UA_WorkQueue_enqueue(&server->workQueue, cb, callbackApplication, data);
-#else
+ void *callbackApplication, void *data) {
+ /* Service mutex is not set inside the timer that triggers the callback */
+ /* The following check cannot be used since another thread can take the
+ * serviceMutex during a server_iterate_call. */
+ //UA_LOCK_ASSERT(&server->serviceMutex, 0);
cb(callbackApplication, data);
-#endif
}
UA_UInt16
@@ -23468,12 +22254,15 @@ UA_Server_run_iterate(UA_Server *server, UA_Boolean waitInternal) {
}
}
#endif
+
+ UA_LOCK(&server->serviceMutex);
+
#if defined(UA_ENABLE_DISCOVERY_MULTICAST) && (UA_MULTITHREADING < 200)
- if(server->config.discovery.mdnsEnable) {
- // TODO multicastNextRepeat does not consider new input data (requests)
- // on the socket. It will be handled on the next call. if needed, we
- // need to use select with timeout on the multicast socket
- // server->mdnsSocket (see example in mdnsd library) on higher level.
+ if(server->config.mdnsEnabled) {
+ /* TODO multicastNextRepeat does not consider new input data (requests)
+ * on the socket. It will be handled on the next call. if needed, we
+ * need to use select with timeout on the multicast socket
+ * server->mdnsSocket (see example in mdnsd library) on higher level. */
UA_DateTime multicastNextRepeat = 0;
UA_StatusCode hasNext =
iterateMulticastDiscoveryServer(server, &multicastNextRepeat, true);
@@ -23482,9 +22271,7 @@ UA_Server_run_iterate(UA_Server *server, UA_Boolean waitInternal) {
}
#endif
-#if UA_MULTITHREADING < 200
- UA_WorkQueue_manuallyProcessDelayed(&server->workQueue);
-#endif
+ UA_UNLOCK(&server->serviceMutex);
now = UA_DateTime_nowMonotonic();
timeout = 0;
@@ -23501,23 +22288,12 @@ UA_Server_run_shutdown(UA_Server *server) {
nl->stop(nl, server);
}
-#if UA_MULTITHREADING >= 200
- /* Shut down the workers */
- UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_SERVER,
- "Shutting down %u worker thread(s)",
- (int unsigned)server->workQueue.workersSize);
- UA_WorkQueue_stop(&server->workQueue);
-#endif
-
#ifdef UA_ENABLE_DISCOVERY_MULTICAST
/* Stop multicast discovery */
- if(server->config.discovery.mdnsEnable)
+ if(server->config.mdnsEnabled)
stopMulticastDiscoveryServer(server);
#endif
- /* Execute all delayed callbacks */
- UA_WorkQueue_cleanup(&server->workQueue);
-
return UA_STATUSCODE_GOOD;
}
@@ -23531,8 +22307,8 @@ testShutdownCondition(UA_Server *server) {
UA_StatusCode
UA_Server_run(UA_Server *server, const volatile UA_Boolean *running) {
UA_StatusCode retval = UA_Server_run_startup(server);
- if(retval != UA_STATUSCODE_GOOD)
- return retval;
+ UA_CHECK_STATUS(retval, return retval);
+
#ifdef UA_ENABLE_VALGRIND_INTERACTIVE
size_t loopCount = 0;
#endif
@@ -23553,56 +22329,20 @@ UA_Server_run(UA_Server *server, const volatile UA_Boolean *running) {
return UA_Server_run_shutdown(server);
}
-#ifdef UA_ENABLE_HISTORIZING
-/* Allow insert of historical data */
-UA_Boolean
-UA_Server_AccessControl_allowHistoryUpdateUpdateData(UA_Server *server,
- const UA_NodeId *sessionId, void *sessionContext,
- const UA_NodeId *nodeId,
- UA_PerformUpdateType performInsertReplace,
- const UA_DataValue *value) {
- if(server->config.accessControl.allowHistoryUpdateUpdateData &&
- !server->config.accessControl.allowHistoryUpdateUpdateData(server, &server->config.accessControl,
- sessionId, sessionContext, nodeId,
- performInsertReplace, value)) {
- return false;
- }
- return true;
-}
-
-/* Allow delete of historical data */
-UA_Boolean
-UA_Server_AccessControl_allowHistoryUpdateDeleteRawModified(UA_Server *server,
- const UA_NodeId *sessionId, void *sessionContext,
- const UA_NodeId *nodeId,
- UA_DateTime startTimestamp,
- UA_DateTime endTimestamp,
- bool isDeleteModified) {
- if(server->config.accessControl.allowHistoryUpdateDeleteRawModified &&
- !server->config.accessControl.allowHistoryUpdateDeleteRawModified(server, &server->config.accessControl,
- sessionId, sessionContext, nodeId,
- startTimestamp, endTimestamp,
- isDeleteModified)) {
- return false;
- }
- return true;
-
-}
-#endif /* UA_ENABLE_HISTORIZING */
-
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/src/server/ua_server_ns0.c" ***********************************/
+/**** amalgamated original file "/src/server/ua_server_ns0.c" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
- * Copyright 2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
+ * Copyright 2017-2022 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
* Copyright 2017 (c) Stefan Profanter, fortiss GmbH
* Copyright 2017 (c) Thomas Bender
* Copyright 2017 (c) Julian Grothoff
* Copyright 2017 (c) Henrik Norrman
* Copyright 2018 (c) Fabian Arndt, Root-Core
* Copyright 2019 (c) Kalycito Infotech Private Limited
+ * Copyright 2021 (c) Christian von Arnim, ISW University of Stuttgart (for VDW and umati)
*/
@@ -23616,9 +22356,8 @@ addNode_raw(UA_Server *server, UA_NodeClass nodeClass,
item.nodeClass = nodeClass;
item.requestedNewNodeId.nodeId = UA_NODEID_NUMERIC(0, nodeId);
item.browseName = UA_QUALIFIEDNAME(0, name);
- item.nodeAttributes.encoding = UA_EXTENSIONOBJECT_DECODED_NODELETE;
- item.nodeAttributes.content.decoded.data = attributes;
- item.nodeAttributes.content.decoded.type = attributesType;
+ UA_ExtensionObject_setValueNoDelete(&item.nodeAttributes,
+ attributes, attributesType);
return AddNode_raw(server, &server->adminSession, NULL, &item, NULL);
}
@@ -23629,7 +22368,7 @@ addNode_finish(UA_Server *server, UA_UInt32 nodeId,
const UA_NodeId refTypeId = UA_NODEID_NUMERIC(0, referenceTypeId);
const UA_ExpandedNodeId targetId = UA_EXPANDEDNODEID_NUMERIC(0, parentNodeId);
UA_StatusCode retval = UA_Server_addReference(server, sourceId, refTypeId, targetId, false);
- if (retval != UA_STATUSCODE_GOOD)
+ if(retval != UA_STATUSCODE_GOOD)
return retval;
return AddNode_finish(server, &server->adminSession, &sourceId);
}
@@ -23670,7 +22409,10 @@ addReferenceTypeNode(UA_Server *server, char* name, char *inverseName, UA_UInt32
* compiler. */
static UA_StatusCode
UA_Server_createNS0_base(UA_Server *server) {
- /* Bootstrap References and HasSubtype */
+ /* Bootstrap ReferenceTypes. The order of these is important for the
+ * ReferenceTypeIndex. The ReferenceTypeIndex is created with the raw node.
+ * The ReferenceTypeSet of subtypes for every ReferenceType is created
+ * during the call to AddNode_finish. */
UA_StatusCode ret = UA_STATUSCODE_GOOD;
UA_ReferenceTypeAttributes references_attr = UA_ReferenceTypeAttributes_default;
references_attr.displayName = UA_LOCALIZEDTEXT("", "References");
@@ -23744,6 +22486,9 @@ UA_Server_createNS0_base(UA_Server *server) {
ret |= addReferenceTypeNode(server, "HasOrderedComponent", "OrderedComponentOf",
UA_NS0ID_HASORDEREDCOMPONENT, false, false, UA_NS0ID_HASCOMPONENT);
+ ret |= addReferenceTypeNode(server, "HasInterface", "InterfaceOf",
+ UA_NS0ID_HASINTERFACE, false, false, UA_NS0ID_NONHIERARCHICALREFERENCES);
+
/**************/
/* Data Types */
/**************/
@@ -23912,7 +22657,8 @@ readStatus(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext,
statustype->secondsTillShutdown = 0;
if(server->endTime != 0) {
statustype->state = UA_SERVERSTATE_SHUTDOWN;
- statustype->secondsTillShutdown = (UA_UInt32)((server->endTime - UA_DateTime_now()) / UA_DATETIME_SEC);
+ statustype->secondsTillShutdown = (UA_UInt32)
+ ((server->endTime - UA_DateTime_now()) / UA_DATETIME_SEC);
}
value->value.data = statustype;
@@ -24124,9 +22870,13 @@ readMinSamplingInterval(UA_Server *server, const UA_NodeId *sessionId, void *ses
}
UA_StatusCode retval;
- retval = UA_Variant_setScalarCopy(&value->value,
- &server->config.samplingIntervalLimits.min,
- &UA_TYPES[UA_TYPES_DURATION]);
+ UA_Duration minInterval;
+#ifdef UA_ENABLE_SUBSCRIPTIONS
+ minInterval = server->config.samplingIntervalLimits.min;
+#else
+ minInterval = 0.0;
+#endif
+ retval = UA_Variant_setScalarCopy(&value->value, &minInterval, &UA_TYPES[UA_TYPES_DURATION]);
if(retval != UA_STATUSCODE_GOOD)
return retval;
value->hasValue = true;
@@ -24142,53 +22892,77 @@ readMinSamplingInterval(UA_Server *server, const UA_NodeId *sessionId, void *ses
static UA_StatusCode
readMonitoredItems(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext,
const UA_NodeId *methodId, void *methodContext, const UA_NodeId *objectId,
- void *objectContext, size_t inputSize,
- const UA_Variant *input, size_t outputSize,
- UA_Variant *output) {
- UA_LOCK(server->serviceMutex);
+ void *objectContext, size_t inputSize, const UA_Variant *input,
+ size_t outputSize, UA_Variant *output) {
+ /* Return two empty arrays by default */
+ UA_Variant_setArray(&output[0], UA_Array_new(0, &UA_TYPES[UA_TYPES_UINT32]),
+ 0, &UA_TYPES[UA_TYPES_UINT32]);
+ UA_Variant_setArray(&output[1], UA_Array_new(0, &UA_TYPES[UA_TYPES_UINT32]),
+ 0, &UA_TYPES[UA_TYPES_UINT32]);
+
+ /* Get the Session */
+ UA_LOCK(&server->serviceMutex);
UA_Session *session = UA_Server_getSessionById(server, sessionId);
- UA_UNLOCK(server->serviceMutex);
- if(!session)
+ if(!session) {
+ UA_UNLOCK(&server->serviceMutex);
return UA_STATUSCODE_BADINTERNALERROR;
- if (inputSize == 0 || !input[0].data)
+ }
+ if(inputSize == 0 || !input[0].data) {
+ UA_UNLOCK(&server->serviceMutex);
return UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
- UA_UInt32 subscriptionId = *((UA_UInt32*)(input[0].data));
- UA_LOCK(server->serviceMutex);
- UA_Subscription* subscription = UA_Session_getSubscriptionById(session, subscriptionId);
- UA_UNLOCK(server->serviceMutex);
- if(!subscription)
- {
- if(LIST_EMPTY(&session->serverSubscriptions))
- {
- UA_Variant_setArray(&output[0], UA_Array_new(0, &UA_TYPES[UA_TYPES_UINT32]),
- 0, &UA_TYPES[UA_TYPES_UINT32]);
- UA_Variant_setArray(&output[1], UA_Array_new(0, &UA_TYPES[UA_TYPES_UINT32]),
- 0, &UA_TYPES[UA_TYPES_UINT32]);
-
- return UA_STATUSCODE_BADNOMATCH;
- }
+ }
+ /* Get the Subscription */
+ UA_UInt32 subscriptionId = *((UA_UInt32*)(input[0].data));
+ UA_Subscription *subscription = UA_Server_getSubscriptionById(server, subscriptionId);
+ if(!subscription) {
+ UA_UNLOCK(&server->serviceMutex);
return UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
}
+ /* The Subscription is not attached to this Session */
+ if(subscription->session != session) {
+ UA_UNLOCK(&server->serviceMutex);
+ return UA_STATUSCODE_BADUSERACCESSDENIED;
+ }
+
+ /* Count the MonitoredItems */
UA_UInt32 sizeOfOutput = 0;
UA_MonitoredItem* monitoredItem;
LIST_FOREACH(monitoredItem, &subscription->monitoredItems, listEntry) {
++sizeOfOutput;
}
- if(sizeOfOutput==0)
+ if(sizeOfOutput == 0) {
+ UA_UNLOCK(&server->serviceMutex);
return UA_STATUSCODE_GOOD;
+ }
- UA_UInt32* clientHandles = (UA_UInt32 *)UA_Array_new(sizeOfOutput, &UA_TYPES[UA_TYPES_UINT32]);
- UA_UInt32* serverHandles = (UA_UInt32 *)UA_Array_new(sizeOfOutput, &UA_TYPES[UA_TYPES_UINT32]);
+ /* Allocate the output arrays */
+ UA_UInt32 *clientHandles = (UA_UInt32*)
+ UA_Array_new(sizeOfOutput, &UA_TYPES[UA_TYPES_UINT32]);
+ if(!clientHandles) {
+ UA_UNLOCK(&server->serviceMutex);
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ }
+ UA_UInt32 *serverHandles = (UA_UInt32*)
+ UA_Array_new(sizeOfOutput, &UA_TYPES[UA_TYPES_UINT32]);
+ if(!serverHandles) {
+ UA_UNLOCK(&server->serviceMutex);
+ UA_free(clientHandles);
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ }
+
+ /* Fill the array */
UA_UInt32 i = 0;
LIST_FOREACH(monitoredItem, &subscription->monitoredItems, listEntry) {
- clientHandles[i] = monitoredItem->clientHandle;
+ clientHandles[i] = monitoredItem->parameters.clientHandle;
serverHandles[i] = monitoredItem->monitoredItemId;
++i;
}
UA_Variant_setArray(&output[0], serverHandles, sizeOfOutput, &UA_TYPES[UA_TYPES_UINT32]);
UA_Variant_setArray(&output[1], clientHandles, sizeOfOutput, &UA_TYPES[UA_TYPES_UINT32]);
+
+ UA_UNLOCK(&server->serviceMutex);
return UA_STATUSCODE_GOOD;
}
#endif /* defined(UA_ENABLE_METHODCALLS) && defined(UA_ENABLE_SUBSCRIPTIONS) */
@@ -24231,6 +23005,7 @@ UA_Server_minimalServerObject(UA_Server *server) {
retval |= addVariableNode(server, "ServerArray", UA_NS0ID_SERVER_SERVERARRAY,
UA_NS0ID_SERVER, UA_NS0ID_HASPROPERTY,
UA_VALUERANK_ANY, UA_NS0ID_BASEDATATYPE);
+
retval |= addVariableNode(server, "NamespaceArray", UA_NS0ID_SERVER_NAMESPACEARRAY,
UA_NS0ID_SERVER, UA_NS0ID_HASPROPERTY,
UA_VALUERANK_ANY, UA_NS0ID_BASEDATATYPE);
@@ -24347,27 +23122,25 @@ addModellingRules(UA_Server *server) {
* example server time. */
UA_StatusCode
UA_Server_initNS0(UA_Server *server) {
-
/* Initialize base nodes which are always required an cannot be created
* through the NS compiler */
server->bootstrapNS0 = true;
UA_StatusCode retVal = UA_Server_createNS0_base(server);
- server->bootstrapNS0 = false;
- if(retVal != UA_STATUSCODE_GOOD)
- return retVal;
#ifdef UA_GENERATED_NAMESPACE_ZERO
/* Load nodes and references generated from the XML ns0 definition */
- retVal = namespace0_generated(server);
+ retVal |= namespace0_generated(server);
#else
/* Create a minimal server object */
- retVal = UA_Server_minimalServerObject(server);
+ retVal |= UA_Server_minimalServerObject(server);
#endif
+ server->bootstrapNS0 = false;
+
if(retVal != UA_STATUSCODE_GOOD) {
UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
- "Initialization of Namespace 0 (before bootstrapping) "
- "failed with %s. See previous outputs for any error messages.",
+ "Initialization of Namespace 0 failed with %s. "
+ "See previous outputs for any error messages.",
UA_StatusCode_name(retVal));
return UA_STATUSCODE_BADINTERNALERROR;
}
@@ -24394,8 +23167,9 @@ UA_Server_initNS0(UA_Server *server) {
/* CurrentTime */
UA_DataSource currentTime = {readCurrentTime, NULL};
- retVal |= UA_Server_setVariableNode_dataSource(server,
- UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_CURRENTTIME), currentTime);
+ UA_NodeId currTime = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_CURRENTTIME);
+ retVal |= UA_Server_setVariableNode_dataSource(server, currTime, currentTime);
+ retVal |= UA_Server_writeMinimumSamplingInterval(server, currTime, 100.0);
/* State */
retVal |= UA_Server_setVariableNode_dataSource(server,
@@ -24454,15 +23228,12 @@ UA_Server_initNS0(UA_Server *server) {
retVal |= UA_Server_setVariableNode_dataSource(server,
UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVICELEVEL), serviceLevel);
- /* ServerDiagnostics - ServerDiagnosticsSummary */
- UA_ServerDiagnosticsSummaryDataType serverDiagnosticsSummary;
- UA_ServerDiagnosticsSummaryDataType_init(&serverDiagnosticsSummary);
- retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY,
- &serverDiagnosticsSummary,
- &UA_TYPES[UA_TYPES_SERVERDIAGNOSTICSSUMMARYDATATYPE]);
-
/* ServerDiagnostics - EnabledFlag */
+#ifdef UA_ENABLE_DIAGNOSTICS
+ UA_Boolean enabledFlag = true;
+#else
UA_Boolean enabledFlag = false;
+#endif
retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_ENABLEDFLAG,
&enabledFlag, &UA_TYPES[UA_TYPES_BOOLEAN]);
@@ -24562,7 +23333,6 @@ UA_Server_initNS0(UA_Server *server) {
retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXMONITOREDITEMSPERCALL,
&server->config.maxMonitoredItemsPerCall, &UA_TYPES[UA_TYPES_UINT32]);
-#ifdef UA_ENABLE_MICRO_EMB_DEV_PROFILE
/* Remove unused operation limit components */
UA_Server_deleteNode(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERHISTORYREADDATA), true);
UA_Server_deleteNode(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERHISTORYREADEVENTS), true);
@@ -24573,26 +23343,100 @@ UA_Server_initNS0(UA_Server *server) {
UA_Server_deleteNode(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERCAPABILITIES_MAXARRAYLENGTH), true);
UA_Server_deleteNode(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERCAPABILITIES_MAXBYTESTRINGLENGTH), true);
- /* Remove not supported Server Instance */
- UA_Server_deleteNode(server, UA_NODEID_NUMERIC(0, UA_NS0ID_DICTIONARIES), true);
+ /* Remove not supported server configurations */
UA_Server_deleteNode(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_ESTIMATEDRETURNTIME), true);
UA_Server_deleteNode(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_LOCALTIME), true);
- UA_Server_deleteNode(server, UA_NODEID_NUMERIC(0, UA_NS0ID_PUBLISHSUBSCRIBE), true);
- UA_Server_deleteNode(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_NAMESPACES), true);
UA_Server_deleteNode(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_REQUESTSERVERSTATECHANGE), true);
UA_Server_deleteNode(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_RESENDDATA), true);
UA_Server_deleteNode(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVERCONFIGURATION), true);
UA_Server_deleteNode(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SETSUBSCRIPTIONDURABLE), true);
+#ifdef UA_ENABLE_DIAGNOSTICS
+ /* ServerDiagnostics - ServerDiagnosticsSummary */
+ UA_DataSource serverDiagSummary = {readDiagnostics, NULL};
+ retVal |= UA_Server_setVariableNode_dataSource(server,
+ UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY), serverDiagSummary);
+
+ /* ServerDiagnostics - ServerDiagnosticsSummary - ServerViewCount */
+ retVal |= UA_Server_setVariableNode_dataSource(server,
+ UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_SERVERVIEWCOUNT), serverDiagSummary);
+
+ /* ServerDiagnostics - ServerDiagnosticsSummary - CurrentSessionCount */
+ retVal |= UA_Server_setVariableNode_dataSource(server,
+ UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_CURRENTSESSIONCOUNT), serverDiagSummary);
+
+ /* ServerDiagnostics - ServerDiagnosticsSummary - CumulatedSessionCount */
+ retVal |= UA_Server_setVariableNode_dataSource(server,
+ UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_CUMULATEDSESSIONCOUNT), serverDiagSummary);
+
+ /* ServerDiagnostics - ServerDiagnosticsSummary - SecurityRejectedSessionCount */
+ retVal |= UA_Server_setVariableNode_dataSource(server,
+ UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_SECURITYREJECTEDSESSIONCOUNT), serverDiagSummary);
+
+ /* ServerDiagnostics - ServerDiagnosticsSummary - RejectedSessionCount */
+ retVal |= UA_Server_setVariableNode_dataSource(server,
+ UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_REJECTEDSESSIONCOUNT), serverDiagSummary);
+
+ /* ServerDiagnostics - ServerDiagnosticsSummary - SessionTimeoutCount */
+ retVal |= UA_Server_setVariableNode_dataSource(server,
+ UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_SESSIONTIMEOUTCOUNT), serverDiagSummary);
+
+ /* ServerDiagnostics - ServerDiagnosticsSummary - SessionAbortCount */
+ retVal |= UA_Server_setVariableNode_dataSource(server,
+ UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_SESSIONABORTCOUNT), serverDiagSummary);
+
+ /* ServerDiagnostics - ServerDiagnosticsSummary - CurrentSubscriptionCount */
+ retVal |= UA_Server_setVariableNode_dataSource(server,
+ UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_CURRENTSUBSCRIPTIONCOUNT), serverDiagSummary);
+
+ /* ServerDiagnostics - ServerDiagnosticsSummary - CumulatedSubscriptionCount */
+ retVal |= UA_Server_setVariableNode_dataSource(server,
+ UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_CUMULATEDSUBSCRIPTIONCOUNT), serverDiagSummary);
+
+ /* ServerDiagnostics - ServerDiagnosticsSummary - PublishingIntervalCount */
+ retVal |= UA_Server_setVariableNode_dataSource(server,
+ UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_PUBLISHINGINTERVALCOUNT), serverDiagSummary);
+
+ /* ServerDiagnostics - ServerDiagnosticsSummary - SecurityRejectedRequestsCount */
+ retVal |= UA_Server_setVariableNode_dataSource(server,
+ UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_SECURITYREJECTEDREQUESTSCOUNT), serverDiagSummary);
+
+ /* ServerDiagnostics - ServerDiagnosticsSummary - RejectedRequestsCount */
+ retVal |= UA_Server_setVariableNode_dataSource(server,
+ UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_REJECTEDREQUESTSCOUNT), serverDiagSummary);
+
+ /* ServerDiagnostics - SubscriptionDiagnosticsArray */
+#ifdef UA_ENABLE_SUBSCRIPTIONS
+ UA_DataSource serverSubDiagSummary = {readSubscriptionDiagnosticsArray, NULL};
+ retVal |= UA_Server_setVariableNode_dataSource(server,
+ UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SUBSCRIPTIONDIAGNOSTICSARRAY), serverSubDiagSummary);
+#endif
+
+ /* ServerDiagnostics - SessionDiagnosticsSummary - SessionDiagnosticsArray */
+ UA_DataSource sessionDiagSummary = {readSessionDiagnosticsArray, NULL};
+ retVal |= UA_Server_setVariableNode_dataSource(server,
+ UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SESSIONSDIAGNOSTICSSUMMARY_SESSIONDIAGNOSTICSARRAY), sessionDiagSummary);
+
+ /* ServerDiagnostics - SessionDiagnosticsSummary - SessionSecurityDiagnosticsArray */
+ UA_DataSource sessionSecDiagSummary = {readSessionSecurityDiagnostics, NULL};
+ retVal |= UA_Server_setVariableNode_dataSource(server,
+ UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SESSIONSDIAGNOSTICSSUMMARY_SESSIONSECURITYDIAGNOSTICSARRAY), sessionSecDiagSummary);
+
+#else
+ /* Removing these NodeIds make Server Object to be non-complaint with UA
+ * 1.03 in CTT (Base Inforamtion/Base Info Core Structure/ 001.js) In the
+ * 1.04 specification this has been resolved by allowing to remove these
+ * static nodes as well */
UA_Server_deleteNode(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SAMPLINGINTERVALDIAGNOSTICSARRAY), true);
UA_Server_deleteNode(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SESSIONSDIAGNOSTICSSUMMARY), true);
-
- /* Removing these NodeIds make Server Object to be non-complaint with UA 1.03 in CTT (Base Inforamtion/Base Info Core Structure/ 001.js)
- * In the 1.04 specification this has been resolved by allowing to remove these static nodes as well */
UA_Server_deleteNode(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY), true);
UA_Server_deleteNode(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SUBSCRIPTIONDIAGNOSTICSARRAY), true);
#endif
+#ifndef UA_ENABLE_PUBSUB
+ UA_Server_deleteNode(server, UA_NODEID_NUMERIC(0, UA_NS0ID_PUBLISHSUBSCRIBE), true);
+#endif
+
#ifndef UA_ENABLE_HISTORIZING
UA_Server_deleteNode(server, UA_NODEID_NUMERIC(0, UA_NS0ID_HISTORYSERVERCAPABILITIES), true);
#else
@@ -24654,7 +23498,7 @@ UA_Server_initNS0(UA_Server *server) {
#endif
#if defined(UA_ENABLE_METHODCALLS) && defined(UA_ENABLE_SUBSCRIPTIONS)
- retVal |= UA_Server_setMethodNode_callback(server,
+ retVal |= UA_Server_setMethodNodeCallback(server,
UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_GETMONITOREDITEMS), readMonitoredItems);
#endif
@@ -24664,21 +23508,6 @@ UA_Server_initNS0(UA_Server *server) {
#endif /* UA_GENERATED_NAMESPACE_ZERO */
- /* create the OverFlowEventType
- * The EventQueueOverflowEventType is defined as abstract, therefore we can not create an instance of that type
- * directly, but need to create a subtype. This is already posted on the OPC Foundation bug tracker under the
- * following link for clarification: https://opcfoundation-onlineapplications.org/mantis/view.php?id=4206 */
-#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
- UA_ObjectTypeAttributes overflowAttr = UA_ObjectTypeAttributes_default;
- overflowAttr.description = UA_LOCALIZEDTEXT("en-US", "A simple event for indicating a queue overflow.");
- overflowAttr.displayName = UA_LOCALIZEDTEXT("en-US", "SimpleOverflowEventType");
- retVal |= UA_Server_addObjectTypeNode(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SIMPLEOVERFLOWEVENTTYPE),
- UA_NODEID_NUMERIC(0, UA_NS0ID_EVENTQUEUEOVERFLOWEVENTTYPE),
- UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE),
- UA_QUALIFIEDNAME(0, "SimpleOverflowEventType"),
- overflowAttr, NULL, NULL);
-#endif
-
if(retVal != UA_STATUSCODE_GOOD) {
UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
"Initialization of Namespace 0 (after bootstrapping) "
@@ -24689,7 +23518,577 @@ UA_Server_initNS0(UA_Server *server) {
return UA_STATUSCODE_GOOD;
}
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/src/server/ua_server_config.c" ***********************************/
+/**** amalgamated original file "/src/server/ua_server_ns0_diagnostics.c" ****/
+
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Copyright 2022 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
+ */
+
+
+#ifdef UA_ENABLE_DIAGNOSTICS
+
+static UA_Boolean
+equalBrowseName(UA_String *bn, char *n) {
+ UA_String name = UA_STRING(n);
+ return UA_String_equal(bn, &name);
+}
+
+#ifdef UA_ENABLE_SUBSCRIPTIONS
+
+/****************************/
+/* Subscription Diagnostics */
+/****************************/
+
+static void
+fillSubscriptionDiagnostics(UA_Subscription *sub,
+ UA_SubscriptionDiagnosticsDataType *diag) {
+ UA_NodeId_copy(&sub->session->sessionId, &diag->sessionId); /* ignore status */
+ diag->subscriptionId = sub->subscriptionId;
+ diag->priority = sub->priority;
+ diag->publishingInterval = sub->publishingInterval;
+ diag->maxKeepAliveCount = sub->maxKeepAliveCount;
+ diag->maxLifetimeCount = sub->lifeTimeCount;
+ diag->maxNotificationsPerPublish = sub->notificationsPerPublish;
+ diag->publishingEnabled = sub->publishingEnabled;
+ diag->modifyCount = sub->modifyCount;
+ diag->enableCount = sub->enableCount;
+ diag->disableCount = sub->disableCount;
+ diag->republishRequestCount = sub->republishRequestCount;
+ diag->republishMessageRequestCount =
+ sub->republishRequestCount; /* Always equal to the previous republishRequestCount */
+ diag->republishMessageCount = sub->republishMessageCount;
+ diag->transferRequestCount = sub->transferRequestCount;
+ diag->transferredToAltClientCount = sub->transferredToAltClientCount;
+ diag->transferredToSameClientCount = sub->transferredToSameClientCount;
+ diag->publishRequestCount = sub->publishRequestCount;
+ diag->dataChangeNotificationsCount = sub->dataChangeNotificationsCount;
+ diag->eventNotificationsCount = sub->eventNotificationsCount;
+ diag->notificationsCount = sub->notificationsCount;
+ diag->latePublishRequestCount = sub->latePublishRequestCount;
+ diag->currentKeepAliveCount = sub->currentKeepAliveCount;
+ diag->currentLifetimeCount = sub->currentLifetimeCount;
+ diag->unacknowledgedMessageCount = (UA_UInt32)sub->retransmissionQueueSize;
+ diag->discardedMessageCount = sub->discardedMessageCount;
+ diag->monitoredItemCount = sub->monitoredItemsSize;
+ diag->monitoringQueueOverflowCount = sub->monitoringQueueOverflowCount;
+ diag->nextSequenceNumber = sub->nextSequenceNumber;
+ diag->eventQueueOverFlowCount = sub->eventQueueOverFlowCount;
+
+ /* Count the disabled MonitoredItems */
+ UA_MonitoredItem *mon;
+ LIST_FOREACH(mon, &sub->monitoredItems, listEntry) {
+ if(mon->monitoringMode == UA_MONITORINGMODE_DISABLED)
+ diag->disabledMonitoredItemCount++;
+ }
+}
+
+/* The node context points to the subscription */
+static UA_StatusCode
+readSubscriptionDiagnostics(UA_Server *server,
+ const UA_NodeId *sessionId, void *sessionContext,
+ const UA_NodeId *nodeId, void *nodeContext,
+ UA_Boolean sourceTimestamp,
+ const UA_NumericRange *range, UA_DataValue *value) {
+ /* Check the Subscription pointer */
+ UA_Subscription *sub = (UA_Subscription*)nodeContext;
+ if(!sub)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ /* Read the BrowseName */
+ UA_QualifiedName bn;
+ UA_StatusCode res = readWithReadValue(server, nodeId, UA_ATTRIBUTEID_BROWSENAME, &bn);
+ if(res != UA_STATUSCODE_GOOD)
+ return res;
+
+ /* Set the value */
+ UA_SubscriptionDiagnosticsDataType sddt;
+ UA_SubscriptionDiagnosticsDataType_init(&sddt);
+ fillSubscriptionDiagnostics(sub, &sddt);
+
+ char memberName[128];
+ memcpy(memberName, bn.name.data, bn.name.length);
+ memberName[bn.name.length] = 0;
+
+ size_t memberOffset;
+ const UA_DataType *memberType;
+ UA_Boolean isArray;
+ UA_Boolean found =
+ UA_DataType_getStructMember(&UA_TYPES[UA_TYPES_SUBSCRIPTIONDIAGNOSTICSDATATYPE],
+ memberName, &memberOffset, &memberType, &isArray);
+ if(!found) {
+ /* Not the member, but the main subscription diagnostics variable... */
+ memberOffset = 0;
+ memberType = &UA_TYPES[UA_TYPES_SUBSCRIPTIONDIAGNOSTICSDATATYPE];
+ }
+
+ void *content = (void*)(((uintptr_t)&sddt) + memberOffset);
+ res = UA_Variant_setScalarCopy(&value->value, content, memberType);
+ if(UA_LIKELY(res == UA_STATUSCODE_GOOD))
+ value->hasValue = true;
+
+ UA_SubscriptionDiagnosticsDataType_clear(&sddt);
+ UA_QualifiedName_clear(&bn);
+ return res;
+}
+
+/* If the nodeContext == NULL, return all subscriptions in the server.
+ * Otherwise only for the current session. */
+UA_StatusCode
+readSubscriptionDiagnosticsArray(UA_Server *server,
+ const UA_NodeId *sessionId, void *sessionContext,
+ const UA_NodeId *nodeId, void *nodeContext,
+ UA_Boolean sourceTimestamp,
+ const UA_NumericRange *range, UA_DataValue *value) {
+ /* Get the current session */
+ size_t sdSize = 0;
+ UA_Session *session = NULL;
+ session_list_entry *sentry;
+ if(nodeContext) {
+ session = UA_Server_getSessionById(server, sessionId);
+ if(!session)
+ return UA_STATUSCODE_BADINTERNALERROR;
+ sdSize = session->subscriptionsSize;
+ } else {
+ LIST_FOREACH(sentry, &server->sessions, pointers) {
+ sdSize += sentry->session.subscriptionsSize;
+ }
+ }
+
+ /* Allocate the output array */
+ UA_SubscriptionDiagnosticsDataType *sd = (UA_SubscriptionDiagnosticsDataType*)
+ UA_Array_new(sdSize, &UA_TYPES[UA_TYPES_SUBSCRIPTIONDIAGNOSTICSDATATYPE]);
+ if(!sd)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+
+ /* Collect the statistics */
+ size_t i = 0;
+ UA_Subscription *sub;
+ if(session) {
+ TAILQ_FOREACH(sub, &session->subscriptions, sessionListEntry) {
+ fillSubscriptionDiagnostics(sub, &sd[i]);
+ i++;
+ }
+ } else {
+ LIST_FOREACH(sentry, &server->sessions, pointers) {
+ TAILQ_FOREACH(sub, &sentry->session.subscriptions, sessionListEntry) {
+ fillSubscriptionDiagnostics(sub, &sd[i]);
+ i++;
+ }
+ }
+ }
+
+ /* Set the output */
+ value->hasValue = true;
+ UA_Variant_setArray(&value->value, sd, sdSize,
+ &UA_TYPES[UA_TYPES_SUBSCRIPTIONDIAGNOSTICSDATATYPE]);
+ return UA_STATUSCODE_GOOD;
+}
+
+void
+createSubscriptionObject(UA_Server *server, UA_Session *session,
+ UA_Subscription *sub) {
+ UA_ExpandedNodeId *children = NULL;
+ size_t childrenSize = 0;
+ UA_ReferenceTypeSet refTypes;
+ UA_NodeId hasComponent = UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT);
+
+ char subIdStr[32];
+ snprintf(subIdStr, 32, "%u", sub->subscriptionId);
+
+ /* Find the NodeId of the SubscriptionDiagnosticsArray */
+ UA_BrowsePath bp;
+ UA_BrowsePath_init(&bp);
+ bp.startingNode = sub->session->sessionId;
+ UA_RelativePathElement rpe[1];
+ memset(rpe, 0, sizeof(UA_RelativePathElement) * 1);
+ rpe[0].targetName = UA_QUALIFIEDNAME(0, "SubscriptionDiagnosticsArray");
+ bp.relativePath.elements = rpe;
+ bp.relativePath.elementsSize = 1;
+ UA_BrowsePathResult bpr = translateBrowsePathToNodeIds(server, &bp);
+ if(bpr.targetsSize < 1)
+ return;
+
+ /* Create an object for the subscription. Instantiates all the mandatory
+ * children. */
+ UA_VariableAttributes var_attr = UA_VariableAttributes_default;
+ var_attr.displayName.text = UA_STRING(subIdStr);
+ var_attr.dataType = UA_TYPES[UA_TYPES_SUBSCRIPTIONDIAGNOSTICSDATATYPE].typeId;
+ UA_NodeId refId = UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT);
+ UA_QualifiedName browseName = UA_QUALIFIEDNAME(0, subIdStr);
+ UA_NodeId typeId = UA_NODEID_NUMERIC(0, UA_NS0ID_SUBSCRIPTIONDIAGNOSTICSTYPE);
+ UA_NodeId objId = UA_NODEID_NUMERIC(1, 0); /* 0 => assign a random free id */
+ UA_StatusCode res = addNode(server, UA_NODECLASS_VARIABLE,
+ &objId,
+ &bpr.targets[0].targetId.nodeId /* parent */,
+ &refId, browseName, &typeId,
+ (UA_NodeAttributes*)&var_attr,
+ &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES], NULL, &objId);
+ UA_CHECK_STATUS(res, goto cleanup);
+
+ /* Add a second reference from the overall SubscriptionDiagnosticsArray variable */
+ const UA_NodeId subDiagArray =
+ UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SUBSCRIPTIONDIAGNOSTICSARRAY);
+ res = addRef(server, session, &subDiagArray, &refId, &objId, true);
+
+ /* Get all children (including the variable itself) and set the contenxt + callback */
+ res = referenceTypeIndices(server, &hasComponent, &refTypes, false);
+ if(res != UA_STATUSCODE_GOOD)
+ goto cleanup;
+ res = browseRecursive(server, 1, &objId,
+ UA_BROWSEDIRECTION_FORWARD, &refTypes,
+ UA_NODECLASS_VARIABLE, true, &childrenSize, &children);
+ if(res != UA_STATUSCODE_GOOD)
+ goto cleanup;
+
+ /* Add the callback to all variables */
+ UA_DataSource subDiagSource = {readSubscriptionDiagnostics, NULL};
+ for(size_t i = 0; i < childrenSize; i++) {
+ setVariableNode_dataSource(server, children[i].nodeId, subDiagSource);
+ setNodeContext(server, children[i].nodeId, sub);
+ }
+
+ UA_Array_delete(children, childrenSize, &UA_TYPES[UA_TYPES_EXPANDEDNODEID]);
+
+ cleanup:
+ UA_BrowsePathResult_clear(&bpr);
+ if(res != UA_STATUSCODE_GOOD) {
+ UA_LOG_WARNING_SESSION(&server->config.logger, session,
+ "Creating the subscription diagnostics object failed "
+ "with StatusCode %s", UA_StatusCode_name(res));
+ }
+}
+
+#endif /* UA_ENABLE_SUBSCRIPTIONS */
+
+/***********************/
+/* Session Diagnostics */
+/***********************/
+
+static void
+setSessionDiagnostics(UA_Session *session, UA_SessionDiagnosticsDataType *sd) {
+ UA_SessionDiagnosticsDataType_copy(&session->diagnostics, sd);
+ UA_NodeId_copy(&session->sessionId, &sd->sessionId);
+ UA_String_copy(&session->sessionName, &sd->sessionName);
+ UA_ApplicationDescription_copy(&session->clientDescription,
+ &sd->clientDescription);
+ sd->maxResponseMessageSize = session->maxResponseMessageSize;
+#ifdef UA_ENABLE_SUBSCRIPTIONS
+ sd->currentPublishRequestsInQueue = (UA_UInt32)session->responseQueueSize;
+#endif
+ sd->actualSessionTimeout = session->timeout;
+
+ /* Set LocaleIds */
+ UA_StatusCode res =
+ UA_Array_copy(session->localeIds, session->localeIdsSize,
+ (void **)&sd->localeIds, &UA_TYPES[UA_TYPES_STRING]);
+ if(UA_LIKELY(res == UA_STATUSCODE_GOOD))
+ sd->localeIdsSize = session->localeIdsSize;
+
+ /* Set Subscription diagnostics */
+#ifdef UA_ENABLE_SUBSCRIPTIONS
+ sd->currentSubscriptionsCount = (UA_UInt32)session->subscriptionsSize;
+
+ UA_Subscription *sub;
+ TAILQ_FOREACH(sub, &session->subscriptions, sessionListEntry) {
+ sd->currentMonitoredItemsCount += (UA_UInt32)sub->monitoredItemsSize;
+ }
+#endif
+}
+
+UA_StatusCode
+readSessionDiagnosticsArray(UA_Server *server,
+ const UA_NodeId *sessionId, void *sessionContext,
+ const UA_NodeId *nodeId, void *nodeContext,
+ UA_Boolean sourceTimestamp,
+ const UA_NumericRange *range, UA_DataValue *value) {
+ /* Allocate the output array */
+ UA_SessionDiagnosticsDataType *sd = (UA_SessionDiagnosticsDataType*)
+ UA_Array_new(server->sessionCount,
+ &UA_TYPES[UA_TYPES_SESSIONDIAGNOSTICSDATATYPE]);
+ if(!sd)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+
+ /* Collect the statistics */
+ size_t i = 0;
+ session_list_entry *session;
+ LIST_FOREACH(session, &server->sessions, pointers) {
+ setSessionDiagnostics(&session->session, &sd[i]);
+ i++;
+ }
+
+ /* Set the output */
+ value->hasValue = true;
+ UA_Variant_setArray(&value->value, sd, server->sessionCount,
+ &UA_TYPES[UA_TYPES_SESSIONDIAGNOSTICSDATATYPE]);
+ return UA_STATUSCODE_GOOD;
+}
+
+static void
+setSessionSecurityDiagnostics(UA_Session *session,
+ UA_SessionSecurityDiagnosticsDataType *sd) {
+ UA_SessionSecurityDiagnosticsDataType_copy(&session->securityDiagnostics, sd);
+ UA_NodeId_copy(&session->sessionId, &sd->sessionId);
+ UA_SecureChannel *channel = session->header.channel;
+ if(channel) {
+ UA_ByteString_copy(&channel->remoteCertificate, &sd->clientCertificate);
+ UA_String_copy(&channel->securityPolicy->policyUri, &sd->securityPolicyUri);
+ sd->securityMode = channel->securityMode;
+ sd->encoding = UA_STRING_ALLOC("UA Binary"); /* The only one atm */
+ sd->transportProtocol = UA_STRING_ALLOC("opc.tcp"); /* The only one atm */
+ }
+}
+
+static UA_StatusCode
+readSessionDiagnostics(UA_Server *server,
+ const UA_NodeId *sessionId, void *sessionContext,
+ const UA_NodeId *nodeId, void *nodeContext,
+ UA_Boolean sourceTimestamp,
+ const UA_NumericRange *range, UA_DataValue *value) {
+ /* Get the Session */
+ UA_Session *session = UA_Server_getSessionById(server, sessionId);
+ if(!session)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ /* Read the BrowseName */
+ UA_QualifiedName bn;
+ UA_StatusCode res = readWithReadValue(server, nodeId, UA_ATTRIBUTEID_BROWSENAME, &bn);
+ if(res != UA_STATUSCODE_GOOD)
+ return res;
+
+ union {
+ UA_SessionDiagnosticsDataType sddt;
+ UA_SessionSecurityDiagnosticsDataType ssddt;
+ } data;
+ void *content;
+ UA_Boolean isArray = false;
+ const UA_DataType *type = NULL;
+ UA_Boolean securityDiagnostics = false;
+
+ char memberName[128];
+ size_t memberOffset;
+ UA_Boolean found;
+
+ if(equalBrowseName(&bn.name, "SubscriptionDiagnosticsArray")) {
+ /* Reuse the datasource callback. Forward a non-null nodeContext to
+ * indicate that we want to see only the subscriptions for the current
+ * session. */
+ res = readSubscriptionDiagnosticsArray(server, sessionId, sessionContext,
+ nodeId, (void*)0x01,
+ sourceTimestamp, range, value);
+ goto cleanup;
+ } else if(equalBrowseName(&bn.name, "SessionDiagnostics")) {
+ setSessionDiagnostics(session, &data.sddt);
+ content = &data.sddt;
+ type = &UA_TYPES[UA_TYPES_SESSIONDIAGNOSTICSDATATYPE];
+ goto set_value;
+ } else if(equalBrowseName(&bn.name, "SessionSecurityDiagnostics")) {
+ setSessionSecurityDiagnostics(session, &data.ssddt);
+ securityDiagnostics = true;
+ content = &data.ssddt;
+ type = &UA_TYPES[UA_TYPES_SESSIONSECURITYDIAGNOSTICSDATATYPE];
+ goto set_value;
+ }
+
+ /* Try to find the member in SessionDiagnosticsDataType and
+ * SessionSecurityDiagnosticsDataType */
+ memcpy(memberName, bn.name.data, bn.name.length);
+ memberName[bn.name.length] = 0;
+ found = UA_DataType_getStructMember(&UA_TYPES[UA_TYPES_SESSIONDIAGNOSTICSDATATYPE],
+ memberName, &memberOffset, &type, &isArray);
+ if(found) {
+ setSessionDiagnostics(session, &data.sddt);
+ content = (void*)(((uintptr_t)&data.sddt) + memberOffset);
+ } else {
+ found = UA_DataType_getStructMember(&UA_TYPES[UA_TYPES_SESSIONSECURITYDIAGNOSTICSDATATYPE],
+ memberName, &memberOffset, &type, &isArray);
+ if(!found) {
+ res = UA_STATUSCODE_BADNOTIMPLEMENTED;
+ goto cleanup;
+ }
+ setSessionSecurityDiagnostics(session, &data.ssddt);
+ securityDiagnostics = true;
+ content = (void*)(((uintptr_t)&data.ssddt) + memberOffset);
+ }
+
+ set_value:
+ if(!isArray) {
+ res = UA_Variant_setScalarCopy(&value->value, content, type);
+ } else {
+ size_t len = *(size_t*)content;
+ content = (void*)(((uintptr_t)content) + sizeof(size_t));
+ res = UA_Variant_setArrayCopy(&value->value, content, len, type);
+ }
+ if(UA_LIKELY(res == UA_STATUSCODE_GOOD))
+ value->hasValue = true;
+
+ if(securityDiagnostics)
+ UA_SessionSecurityDiagnosticsDataType_clear(&data.ssddt);
+ else
+ UA_SessionDiagnosticsDataType_clear(&data.sddt);
+
+ cleanup:
+ UA_QualifiedName_clear(&bn);
+ return res;
+}
+
+UA_StatusCode
+readSessionSecurityDiagnostics(UA_Server *server,
+ const UA_NodeId *sessionId, void *sessionContext,
+ const UA_NodeId *nodeId, void *nodeContext,
+ UA_Boolean sourceTimestamp,
+ const UA_NumericRange *range, UA_DataValue *value) {
+ /* Allocate the output array */
+ UA_SessionSecurityDiagnosticsDataType *sd = (UA_SessionSecurityDiagnosticsDataType*)
+ UA_Array_new(server->sessionCount,
+ &UA_TYPES[UA_TYPES_SESSIONSECURITYDIAGNOSTICSDATATYPE]);
+ if(!sd)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+
+ /* Collect the statistics */
+ size_t i = 0;
+ session_list_entry *session;
+ LIST_FOREACH(session, &server->sessions, pointers) {
+ setSessionSecurityDiagnostics(&session->session, &sd[i]);
+ i++;
+ }
+
+ /* Set the output */
+ value->hasValue = true;
+ UA_Variant_setArray(&value->value, sd, server->sessionCount,
+ &UA_TYPES[UA_TYPES_SESSIONSECURITYDIAGNOSTICSDATATYPE]);
+ return UA_STATUSCODE_GOOD;
+}
+
+void
+createSessionObject(UA_Server *server, UA_Session *session) {
+ UA_ExpandedNodeId *children = NULL;
+ size_t childrenSize = 0;
+ UA_ReferenceTypeSet refTypes;
+ UA_NodeId hasComponent = UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT);
+
+ /* Create an object for the session. Instantiates all the mandatory children. */
+ UA_ObjectAttributes object_attr = UA_ObjectAttributes_default;
+ object_attr.displayName.text = session->sessionName;
+ UA_NodeId parentId = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SESSIONSDIAGNOSTICSSUMMARY);
+ UA_NodeId refId = UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT);
+ UA_QualifiedName browseName = UA_QUALIFIEDNAME(0, "");
+ browseName.name = session->sessionName; /* shallow copy */
+ UA_NodeId typeId = UA_NODEID_NUMERIC(0, UA_NS0ID_SESSIONDIAGNOSTICSOBJECTTYPE);
+ UA_StatusCode res = addNode(server, UA_NODECLASS_OBJECT,
+ &session->sessionId, &parentId, &refId, browseName, &typeId,
+ (UA_NodeAttributes*)&object_attr,
+ &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES], NULL, NULL);
+ if(res != UA_STATUSCODE_GOOD)
+ goto cleanup;
+
+ /* Recursively browse all children */
+ res = referenceTypeIndices(server, &hasComponent, &refTypes, false);
+ if(res != UA_STATUSCODE_GOOD)
+ goto cleanup;
+ res = browseRecursive(server, 1, &session->sessionId,
+ UA_BROWSEDIRECTION_FORWARD, &refTypes,
+ UA_NODECLASS_VARIABLE, false, &childrenSize, &children);
+ if(res != UA_STATUSCODE_GOOD)
+ goto cleanup;
+
+ /* Add the callback to all variables */
+ UA_DataSource sessionDiagSource = {readSessionDiagnostics, NULL};
+ for(size_t i = 0; i < childrenSize; i++) {
+ setVariableNode_dataSource(server, children[i].nodeId, sessionDiagSource);
+ }
+
+ cleanup:
+ if(res != UA_STATUSCODE_GOOD) {
+ UA_LOG_WARNING_SESSION(&server->config.logger, session,
+ "Creating the session diagnostics object failed "
+ "with StatusCode %s", UA_StatusCode_name(res));
+ }
+ UA_Array_delete(children, childrenSize, &UA_TYPES[UA_TYPES_EXPANDEDNODEID]);
+}
+
+/***************************/
+/* Server-Wide Diagnostics */
+/***************************/
+
+UA_StatusCode
+readDiagnostics(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext,
+ const UA_NodeId *nodeId, void *nodeContext, UA_Boolean sourceTimestamp,
+ const UA_NumericRange *range, UA_DataValue *value) {
+ if(range) {
+ value->hasStatus = true;
+ value->status = UA_STATUSCODE_BADINDEXRANGEINVALID;
+ return UA_STATUSCODE_GOOD;
+ }
+
+ if(sourceTimestamp) {
+ value->hasSourceTimestamp = true;
+ value->sourceTimestamp = UA_DateTime_now();
+ }
+
+ UA_assert(nodeId->identifierType == UA_NODEIDTYPE_NUMERIC);
+
+ void *data = NULL;
+ const UA_DataType *type = &UA_TYPES[UA_TYPES_UINT32]; /* Default */
+
+ switch(nodeId->identifier.numeric) {
+ case UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY:
+ server->serverDiagnosticsSummary.currentSessionCount =
+ server->activeSessionCount;
+ data = &server->serverDiagnosticsSummary;
+ type = &UA_TYPES[UA_TYPES_SERVERDIAGNOSTICSSUMMARYDATATYPE];
+ break;
+ case UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_SERVERVIEWCOUNT:
+ data = &server->serverDiagnosticsSummary.serverViewCount;
+ break;
+ case UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_CURRENTSESSIONCOUNT:
+ data = &server->activeSessionCount;
+ break;
+ case UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_CUMULATEDSESSIONCOUNT:
+ data = &server->serverDiagnosticsSummary.cumulatedSessionCount;
+ break;
+ case UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_SECURITYREJECTEDSESSIONCOUNT:
+ data = &server->serverDiagnosticsSummary.securityRejectedSessionCount;
+ break;
+ case UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_REJECTEDSESSIONCOUNT:
+ data = &server->serverDiagnosticsSummary.rejectedSessionCount;
+ break;
+ case UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_SESSIONTIMEOUTCOUNT:
+ data = &server->serverDiagnosticsSummary.sessionTimeoutCount;
+ break;
+ case UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_SESSIONABORTCOUNT:
+ data = &server->serverDiagnosticsSummary.sessionAbortCount;
+ break;
+ case UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_CURRENTSUBSCRIPTIONCOUNT:
+ data = &server->serverDiagnosticsSummary.currentSubscriptionCount;
+ break;
+ case UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_CUMULATEDSUBSCRIPTIONCOUNT:
+ data = &server->serverDiagnosticsSummary.cumulatedSubscriptionCount;
+ break;
+ case UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_PUBLISHINGINTERVALCOUNT:
+ data = &server->serverDiagnosticsSummary.publishingIntervalCount;
+ break;
+ case UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_SECURITYREJECTEDREQUESTSCOUNT:
+ data = &server->serverDiagnosticsSummary.securityRejectedRequestsCount;
+ break;
+ case UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_REJECTEDREQUESTSCOUNT:
+ data = &server->serverDiagnosticsSummary.rejectedRequestsCount;
+ break;
+ default:
+ return UA_STATUSCODE_BADINTERNALERROR;
+ }
+
+ UA_StatusCode res = UA_Variant_setScalarCopy(&value->value, data, type);
+ if(res == UA_STATUSCODE_GOOD)
+ value->hasValue = true;
+ return res;
+}
+
+#endif /* UA_ENABLE_DIAGNOSTICS */
+
+/**** amalgamated original file "/src/server/ua_server_config.c" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -24706,14 +24105,14 @@ UA_ServerConfig_clean(UA_ServerConfig *config) {
return;
/* Server Description */
- UA_BuildInfo_deleteMembers(&config->buildInfo);
- UA_ApplicationDescription_deleteMembers(&config->applicationDescription);
+ UA_BuildInfo_clear(&config->buildInfo);
+ UA_ApplicationDescription_clear(&config->applicationDescription);
#ifdef UA_ENABLE_DISCOVERY_MULTICAST
- UA_MdnsDiscoveryConfiguration_clear(&config->discovery.mdns);
- UA_String_clear(&config->discovery.mdnsInterfaceIP);
+ UA_MdnsDiscoveryConfiguration_clear(&config->mdnsConfig);
+ UA_String_clear(&config->mdnsInterfaceIP);
# if !defined(UA_HAS_GETIFADDR)
- if (config->discovery.ipAddressListSize) {
- UA_free(config->discovery.ipAddressList);
+ if (config->mdnsIpAddressListSize) {
+ UA_free(config->mdnsIpAddressList);
}
# endif
#endif
@@ -24727,7 +24126,7 @@ UA_ServerConfig_clean(UA_ServerConfig *config) {
UA_free(config->networkLayers);
config->networkLayers = NULL;
config->networkLayersSize = 0;
- UA_String_deleteMembers(&config->customHostname);
+ UA_String_clear(&config->customHostname);
config->customHostname = UA_STRING_NULL;
for(size_t i = 0; i < config->securityPoliciesSize; ++i) {
@@ -24739,7 +24138,7 @@ UA_ServerConfig_clean(UA_ServerConfig *config) {
config->securityPoliciesSize = 0;
for(size_t i = 0; i < config->endpointsSize; ++i)
- UA_EndpointDescription_deleteMembers(&config->endpoints[i]);
+ UA_EndpointDescription_clear(&config->endpoints[i]);
UA_free(config->endpoints);
config->endpoints = NULL;
@@ -24770,15 +24169,19 @@ UA_ServerConfig_clean(UA_ServerConfig *config) {
config->logger.clear(config->logger.context);
config->logger.log = NULL;
config->logger.clear = NULL;
-}
-void
-UA_ServerConfig_setCustomHostname(UA_ServerConfig *config,
- const UA_String customHostname) {
- if(!config)
- return;
- UA_String_deleteMembers(&config->customHostname);
- UA_String_copy(&customHostname, &config->customHostname);
+#ifdef UA_ENABLE_PUBSUB
+#ifdef UA_ENABLE_PUBSUB_ENCRYPTION
+ if(config->pubSubConfig.securityPolicies != NULL) {
+ for(size_t i = 0; i < config->pubSubConfig.securityPoliciesSize; i++) {
+ config->pubSubConfig.securityPolicies[i].clear(&config->pubSubConfig.securityPolicies[i]);
+ }
+ UA_free(config->pubSubConfig.securityPolicies);
+ config->pubSubConfig.securityPolicies = NULL;
+ config->pubSubConfig.securityPoliciesSize = 0;
+ }
+#endif
+#endif /* UA_ENABLE_PUBSUB */
}
#ifdef UA_ENABLE_PUBSUB
@@ -24786,35 +24189,28 @@ UA_ServerConfig_setCustomHostname(UA_ServerConfig *config,
* demand. */
UA_StatusCode
UA_ServerConfig_addPubSubTransportLayer(UA_ServerConfig *config,
- UA_PubSubTransportLayer *pubsubTransportLayer) {
-
- if(config->pubsubTransportLayersSize == 0) {
- config->pubsubTransportLayers = (UA_PubSubTransportLayer *)
- UA_malloc(sizeof(UA_PubSubTransportLayer));
- } else {
- config->pubsubTransportLayers = (UA_PubSubTransportLayer*)
- UA_realloc(config->pubsubTransportLayers,
- sizeof(UA_PubSubTransportLayer) * (config->pubsubTransportLayersSize + 1));
- }
-
- if(config->pubsubTransportLayers == NULL)
+ UA_PubSubTransportLayer pubsubTransportLayer) {
+ UA_PubSubTransportLayer *tmpLayers = (UA_PubSubTransportLayer*)
+ UA_realloc(config->pubSubConfig.transportLayers,
+ sizeof(UA_PubSubTransportLayer) *
+ (config->pubSubConfig.transportLayersSize + 1));
+ if(tmpLayers == NULL)
return UA_STATUSCODE_BADOUTOFMEMORY;
- memcpy(&config->pubsubTransportLayers[config->pubsubTransportLayersSize],
- pubsubTransportLayer, sizeof(UA_PubSubTransportLayer));
- config->pubsubTransportLayersSize++;
-
+ config->pubSubConfig.transportLayers = tmpLayers;
+ config->pubSubConfig.transportLayers[config->pubSubConfig.transportLayersSize] = pubsubTransportLayer;
+ config->pubSubConfig.transportLayersSize++;
return UA_STATUSCODE_GOOD;
}
#endif /* UA_ENABLE_PUBSUB */
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/src/server/ua_server_binary.c" ***********************************/
+/**** amalgamated original file "/src/server/ua_server_binary.c" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
- * Copyright 2014-2020 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
+ * Copyright 2014-2022 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
* Copyright 2014-2016 (c) Sten Grüner
* Copyright 2014-2015, 2017 (c) Florian Palm
* Copyright 2015-2016 (c) Chris Iatrou
@@ -24845,10 +24241,10 @@ void UA_debug_dumpCompleteChunk(UA_Server *const server, UA_Connection *const co
/********************/
UA_StatusCode
-sendServiceFault(UA_SecureChannel *channel, UA_UInt32 requestId, UA_UInt32 requestHandle,
- const UA_DataType *responseType, UA_StatusCode statusCode) {
- UA_Response response;
- UA_init(&response, responseType);
+sendServiceFault(UA_SecureChannel *channel, UA_UInt32 requestId,
+ UA_UInt32 requestHandle, UA_StatusCode statusCode) {
+ UA_ServiceFault response;
+ UA_ServiceFault_init(&response);
UA_ResponseHeader *responseHeader = &response.responseHeader;
responseHeader->requestHandle = requestHandle;
responseHeader->timestamp = UA_DateTime_now();
@@ -24860,29 +24256,40 @@ sendServiceFault(UA_SecureChannel *channel, UA_UInt32 requestId, UA_UInt32 reque
/* Send error message. Message type is MSG and not ERR, since we are on a
* SecureChannel! */
- return UA_SecureChannel_sendSymmetricMessage(channel, requestId, UA_MESSAGETYPE_MSG,
- &response, responseType);
+ return UA_SecureChannel_sendSymmetricMessage(channel, requestId,
+ UA_MESSAGETYPE_MSG, &response,
+ &UA_TYPES[UA_TYPES_SERVICEFAULT]);
}
- /* This is not an ERR message, the connection is not closed afterwards */
+/* This is not an ERR message, the connection is not closed afterwards */
static UA_StatusCode
decodeHeaderSendServiceFault(UA_SecureChannel *channel, const UA_ByteString *msg,
size_t offset, const UA_DataType *responseType,
UA_UInt32 requestId, UA_StatusCode error) {
UA_RequestHeader requestHeader;
- UA_StatusCode retval = UA_RequestHeader_decodeBinary(msg, &offset, &requestHeader);
+ UA_StatusCode retval =
+ UA_decodeBinaryInternal(msg, &offset, &requestHeader,
+ &UA_TYPES[UA_TYPES_REQUESTHEADER], NULL);
if(retval != UA_STATUSCODE_GOOD)
return retval;
- retval = sendServiceFault(channel, requestId, requestHeader.requestHandle,
- responseType, error);
+ retval = sendServiceFault(channel, requestId, requestHeader.requestHandle, error);
UA_RequestHeader_clear(&requestHeader);
return retval;
}
+/* The counterOffset is the offset of the UA_ServiceCounterDataType for the
+ * service in the UA_ SessionDiagnosticsDataType. */
+#ifdef UA_ENABLE_DIAGNOSTICS
+#define UA_SERVICECOUNTER_OFFSET(X) \
+ *counterOffset = offsetof(UA_SessionDiagnosticsDataType, X)
+#else
+#define UA_SERVICECOUNTER_OFFSET(X)
+#endif
+
static void
getServicePointers(UA_UInt32 requestTypeId, const UA_DataType **requestType,
const UA_DataType **responseType, UA_Service *service,
- UA_Boolean *requiresSession) {
+ UA_Boolean *requiresSession, size_t *counterOffset) {
switch(requestTypeId) {
case UA_NS0ID_GETENDPOINTSREQUEST_ENCODING_DEFAULTBINARY:
*service = (UA_Service)Service_GetEndpoints;
@@ -24919,18 +24326,18 @@ getServicePointers(UA_UInt32 requestTypeId, const UA_DataType **requestType,
break;
#endif
case UA_NS0ID_CREATESESSIONREQUEST_ENCODING_DEFAULTBINARY:
- *service = (UA_Service)(uintptr_t)Service_CreateSession;
+ *service = (UA_Service)Service_CreateSession;
*requestType = &UA_TYPES[UA_TYPES_CREATESESSIONREQUEST];
*responseType = &UA_TYPES[UA_TYPES_CREATESESSIONRESPONSE];
*requiresSession = false;
break;
case UA_NS0ID_ACTIVATESESSIONREQUEST_ENCODING_DEFAULTBINARY:
- *service = (UA_Service)(uintptr_t)Service_ActivateSession;
+ *service = (UA_Service)Service_ActivateSession;
*requestType = &UA_TYPES[UA_TYPES_ACTIVATESESSIONREQUEST];
*responseType = &UA_TYPES[UA_TYPES_ACTIVATESESSIONRESPONSE];
break;
case UA_NS0ID_CLOSESESSIONREQUEST_ENCODING_DEFAULTBINARY:
- *service = (UA_Service)(uintptr_t)Service_CloseSession;
+ *service = (UA_Service)Service_CloseSession;
*requestType = &UA_TYPES[UA_TYPES_CLOSESESSIONREQUEST];
*responseType = &UA_TYPES[UA_TYPES_CLOSESESSIONRESPONSE];
break;
@@ -24939,36 +24346,43 @@ getServicePointers(UA_UInt32 requestTypeId, const UA_DataType **requestType,
*service = (UA_Service)Service_Read;
*requestType = &UA_TYPES[UA_TYPES_READREQUEST];
*responseType = &UA_TYPES[UA_TYPES_READRESPONSE];
+ UA_SERVICECOUNTER_OFFSET(readCount);
break;
case UA_NS0ID_WRITEREQUEST_ENCODING_DEFAULTBINARY:
*service = (UA_Service)Service_Write;
*requestType = &UA_TYPES[UA_TYPES_WRITEREQUEST];
*responseType = &UA_TYPES[UA_TYPES_WRITERESPONSE];
+ UA_SERVICECOUNTER_OFFSET(writeCount);
break;
case UA_NS0ID_BROWSEREQUEST_ENCODING_DEFAULTBINARY:
*service = (UA_Service)Service_Browse;
*requestType = &UA_TYPES[UA_TYPES_BROWSEREQUEST];
*responseType = &UA_TYPES[UA_TYPES_BROWSERESPONSE];
+ UA_SERVICECOUNTER_OFFSET(browseCount);
break;
case UA_NS0ID_BROWSENEXTREQUEST_ENCODING_DEFAULTBINARY:
*service = (UA_Service)Service_BrowseNext;
*requestType = &UA_TYPES[UA_TYPES_BROWSENEXTREQUEST];
*responseType = &UA_TYPES[UA_TYPES_BROWSENEXTRESPONSE];
+ UA_SERVICECOUNTER_OFFSET(browseNextCount);
break;
case UA_NS0ID_REGISTERNODESREQUEST_ENCODING_DEFAULTBINARY:
*service = (UA_Service)Service_RegisterNodes;
*requestType = &UA_TYPES[UA_TYPES_REGISTERNODESREQUEST];
*responseType = &UA_TYPES[UA_TYPES_REGISTERNODESRESPONSE];
+ UA_SERVICECOUNTER_OFFSET(registerNodesCount);
break;
case UA_NS0ID_UNREGISTERNODESREQUEST_ENCODING_DEFAULTBINARY:
*service = (UA_Service)Service_UnregisterNodes;
*requestType = &UA_TYPES[UA_TYPES_UNREGISTERNODESREQUEST];
*responseType = &UA_TYPES[UA_TYPES_UNREGISTERNODESRESPONSE];
+ UA_SERVICECOUNTER_OFFSET(unregisterNodesCount);
break;
case UA_NS0ID_TRANSLATEBROWSEPATHSTONODEIDSREQUEST_ENCODING_DEFAULTBINARY:
*service = (UA_Service)Service_TranslateBrowsePathsToNodeIds;
*requestType = &UA_TYPES[UA_TYPES_TRANSLATEBROWSEPATHSTONODEIDSREQUEST];
*responseType = &UA_TYPES[UA_TYPES_TRANSLATEBROWSEPATHSTONODEIDSRESPONSE];
+ UA_SERVICECOUNTER_OFFSET(translateBrowsePathsToNodeIdsCount);
break;
#ifdef UA_ENABLE_SUBSCRIPTIONS
@@ -24976,50 +24390,72 @@ getServicePointers(UA_UInt32 requestTypeId, const UA_DataType **requestType,
*service = (UA_Service)Service_CreateSubscription;
*requestType = &UA_TYPES[UA_TYPES_CREATESUBSCRIPTIONREQUEST];
*responseType = &UA_TYPES[UA_TYPES_CREATESUBSCRIPTIONRESPONSE];
+ UA_SERVICECOUNTER_OFFSET(createSubscriptionCount);
break;
case UA_NS0ID_PUBLISHREQUEST_ENCODING_DEFAULTBINARY:
*requestType = &UA_TYPES[UA_TYPES_PUBLISHREQUEST];
*responseType = &UA_TYPES[UA_TYPES_PUBLISHRESPONSE];
+ UA_SERVICECOUNTER_OFFSET(publishCount);
break;
case UA_NS0ID_REPUBLISHREQUEST_ENCODING_DEFAULTBINARY:
*service = (UA_Service)Service_Republish;
*requestType = &UA_TYPES[UA_TYPES_REPUBLISHREQUEST];
*responseType = &UA_TYPES[UA_TYPES_REPUBLISHRESPONSE];
+ UA_SERVICECOUNTER_OFFSET(republishCount);
break;
case UA_NS0ID_MODIFYSUBSCRIPTIONREQUEST_ENCODING_DEFAULTBINARY:
*service = (UA_Service)Service_ModifySubscription;
*requestType = &UA_TYPES[UA_TYPES_MODIFYSUBSCRIPTIONREQUEST];
*responseType = &UA_TYPES[UA_TYPES_MODIFYSUBSCRIPTIONRESPONSE];
+ UA_SERVICECOUNTER_OFFSET(modifySubscriptionCount);
break;
case UA_NS0ID_SETPUBLISHINGMODEREQUEST_ENCODING_DEFAULTBINARY:
*service = (UA_Service)Service_SetPublishingMode;
*requestType = &UA_TYPES[UA_TYPES_SETPUBLISHINGMODEREQUEST];
*responseType = &UA_TYPES[UA_TYPES_SETPUBLISHINGMODERESPONSE];
+ UA_SERVICECOUNTER_OFFSET(setPublishingModeCount);
break;
case UA_NS0ID_DELETESUBSCRIPTIONSREQUEST_ENCODING_DEFAULTBINARY:
*service = (UA_Service)Service_DeleteSubscriptions;
*requestType = &UA_TYPES[UA_TYPES_DELETESUBSCRIPTIONSREQUEST];
*responseType = &UA_TYPES[UA_TYPES_DELETESUBSCRIPTIONSRESPONSE];
+ UA_SERVICECOUNTER_OFFSET(deleteSubscriptionsCount);
+ break;
+ case UA_NS0ID_TRANSFERSUBSCRIPTIONSREQUEST_ENCODING_DEFAULTBINARY:
+ *service = (UA_Service)Service_TransferSubscriptions;
+ *requestType = &UA_TYPES[UA_TYPES_TRANSFERSUBSCRIPTIONSREQUEST];
+ *responseType = &UA_TYPES[UA_TYPES_TRANSFERSUBSCRIPTIONSRESPONSE];
+ UA_SERVICECOUNTER_OFFSET(transferSubscriptionsCount);
break;
case UA_NS0ID_CREATEMONITOREDITEMSREQUEST_ENCODING_DEFAULTBINARY:
*service = (UA_Service)Service_CreateMonitoredItems;
*requestType = &UA_TYPES[UA_TYPES_CREATEMONITOREDITEMSREQUEST];
*responseType = &UA_TYPES[UA_TYPES_CREATEMONITOREDITEMSRESPONSE];
+ UA_SERVICECOUNTER_OFFSET(createMonitoredItemsCount);
break;
case UA_NS0ID_DELETEMONITOREDITEMSREQUEST_ENCODING_DEFAULTBINARY:
*service = (UA_Service)Service_DeleteMonitoredItems;
*requestType = &UA_TYPES[UA_TYPES_DELETEMONITOREDITEMSREQUEST];
*responseType = &UA_TYPES[UA_TYPES_DELETEMONITOREDITEMSRESPONSE];
+ UA_SERVICECOUNTER_OFFSET(deleteMonitoredItemsCount);
break;
case UA_NS0ID_MODIFYMONITOREDITEMSREQUEST_ENCODING_DEFAULTBINARY:
*service = (UA_Service)Service_ModifyMonitoredItems;
*requestType = &UA_TYPES[UA_TYPES_MODIFYMONITOREDITEMSREQUEST];
*responseType = &UA_TYPES[UA_TYPES_MODIFYMONITOREDITEMSRESPONSE];
+ UA_SERVICECOUNTER_OFFSET(modifyMonitoredItemsCount);
break;
case UA_NS0ID_SETMONITORINGMODEREQUEST_ENCODING_DEFAULTBINARY:
*service = (UA_Service)Service_SetMonitoringMode;
*requestType = &UA_TYPES[UA_TYPES_SETMONITORINGMODEREQUEST];
*responseType = &UA_TYPES[UA_TYPES_SETMONITORINGMODERESPONSE];
+ UA_SERVICECOUNTER_OFFSET(setMonitoringModeCount);
+ break;
+ case UA_NS0ID_SETTRIGGERINGREQUEST_ENCODING_DEFAULTBINARY:
+ *service = (UA_Service)Service_SetTriggering;
+ *requestType = &UA_TYPES[UA_TYPES_SETTRIGGERINGREQUEST];
+ *responseType = &UA_TYPES[UA_TYPES_SETTRIGGERINGRESPONSE];
+ UA_SERVICECOUNTER_OFFSET(setTriggeringCount);
break;
#endif
#ifdef UA_ENABLE_HISTORIZING
@@ -25028,12 +24464,14 @@ getServicePointers(UA_UInt32 requestTypeId, const UA_DataType **requestType,
*service = (UA_Service)Service_HistoryRead;
*requestType = &UA_TYPES[UA_TYPES_HISTORYREADREQUEST];
*responseType = &UA_TYPES[UA_TYPES_HISTORYREADRESPONSE];
+ UA_SERVICECOUNTER_OFFSET(historyReadCount);
break;
/* For History update */
case UA_NS0ID_HISTORYUPDATEREQUEST_ENCODING_DEFAULTBINARY:
*service = (UA_Service)Service_HistoryUpdate;
*requestType = &UA_TYPES[UA_TYPES_HISTORYUPDATEREQUEST];
*responseType = &UA_TYPES[UA_TYPES_HISTORYUPDATERESPONSE];
+ UA_SERVICECOUNTER_OFFSET(historyUpdateCount);
break;
#endif
@@ -25042,6 +24480,7 @@ getServicePointers(UA_UInt32 requestTypeId, const UA_DataType **requestType,
*service = (UA_Service)Service_Call;
*requestType = &UA_TYPES[UA_TYPES_CALLREQUEST];
*responseType = &UA_TYPES[UA_TYPES_CALLRESPONSE];
+ UA_SERVICECOUNTER_OFFSET(callCount);
break;
#endif
@@ -25050,21 +24489,25 @@ getServicePointers(UA_UInt32 requestTypeId, const UA_DataType **requestType,
*service = (UA_Service)Service_AddNodes;
*requestType = &UA_TYPES[UA_TYPES_ADDNODESREQUEST];
*responseType = &UA_TYPES[UA_TYPES_ADDNODESRESPONSE];
+ UA_SERVICECOUNTER_OFFSET(addNodesCount);
break;
case UA_NS0ID_ADDREFERENCESREQUEST_ENCODING_DEFAULTBINARY:
*service = (UA_Service)Service_AddReferences;
*requestType = &UA_TYPES[UA_TYPES_ADDREFERENCESREQUEST];
*responseType = &UA_TYPES[UA_TYPES_ADDREFERENCESRESPONSE];
+ UA_SERVICECOUNTER_OFFSET(addReferencesCount);
break;
case UA_NS0ID_DELETENODESREQUEST_ENCODING_DEFAULTBINARY:
*service = (UA_Service)Service_DeleteNodes;
*requestType = &UA_TYPES[UA_TYPES_DELETENODESREQUEST];
*responseType = &UA_TYPES[UA_TYPES_DELETENODESRESPONSE];
+ UA_SERVICECOUNTER_OFFSET(deleteNodesCount);
break;
case UA_NS0ID_DELETEREFERENCESREQUEST_ENCODING_DEFAULTBINARY:
*service = (UA_Service)Service_DeleteReferences;
*requestType = &UA_TYPES[UA_TYPES_DELETEREFERENCESREQUEST];
*responseType = &UA_TYPES[UA_TYPES_DELETEREFERENCESRESPONSE];
+ UA_SERVICECOUNTER_OFFSET(deleteReferencesCount);
break;
#endif
@@ -25080,9 +24523,13 @@ getServicePointers(UA_UInt32 requestTypeId, const UA_DataType **requestType,
/* HEL -> Open up the connection */
static UA_StatusCode
processHEL(UA_Server *server, UA_SecureChannel *channel, const UA_ByteString *msg) {
- size_t offset = 8; /* Go to the beginning of the TcpHelloMessage */
+ if(channel->state != UA_SECURECHANNELSTATE_FRESH)
+ return UA_STATUSCODE_BADINTERNALERROR;
+ size_t offset = 0; /* Go to the beginning of the TcpHelloMessage */
UA_TcpHelloMessage helloMessage;
- UA_StatusCode retval = UA_TcpHelloMessage_decodeBinary(msg, &offset, &helloMessage);
+ UA_StatusCode retval =
+ UA_decodeBinaryInternal(msg, &offset, &helloMessage,
+ &UA_TRANSPORT[UA_TRANSPORT_TCPHELLOMESSAGE], NULL);
if(retval != UA_STATUSCODE_GOOD)
return retval;
@@ -25123,26 +24570,36 @@ processHEL(UA_Server *server, UA_SecureChannel *channel, const UA_ByteString *ms
/* Encode and send the response */
UA_Byte *bufPos = ack_msg.data;
const UA_Byte *bufEnd = &ack_msg.data[ack_msg.length];
- retval |= UA_TcpMessageHeader_encodeBinary(&ackHeader, &bufPos, bufEnd);
- retval |= UA_TcpAcknowledgeMessage_encodeBinary(&ackMessage, &bufPos, bufEnd);
+ retval |= UA_encodeBinaryInternal(&ackHeader,
+ &UA_TRANSPORT[UA_TRANSPORT_TCPMESSAGEHEADER],
+ &bufPos, &bufEnd, NULL, NULL);
+ retval |= UA_encodeBinaryInternal(&ackMessage,
+ &UA_TRANSPORT[UA_TRANSPORT_TCPACKNOWLEDGEMESSAGE],
+ &bufPos, &bufEnd, NULL, NULL);
if(retval != UA_STATUSCODE_GOOD) {
connection->releaseSendBuffer(connection, &ack_msg);
return retval;
}
ack_msg.length = ackHeader.messageSize;
- return connection->send(connection, &ack_msg);
+ retval = connection->send(connection, &ack_msg);
+ if(retval == UA_STATUSCODE_GOOD)
+ channel->state = UA_SECURECHANNELSTATE_ACK_SENT;
+ return retval;
}
/* OPN -> Open up/renew the securechannel */
static UA_StatusCode
processOPN(UA_Server *server, UA_SecureChannel *channel,
- const UA_UInt32 requestId, const UA_ByteString *msg, size_t offset) {
+ const UA_UInt32 requestId, const UA_ByteString *msg) {
+ if(channel->state != UA_SECURECHANNELSTATE_ACK_SENT &&
+ channel->state != UA_SECURECHANNELSTATE_OPEN)
+ return UA_STATUSCODE_BADINTERNALERROR;
/* Decode the request */
UA_NodeId requestType;
UA_OpenSecureChannelRequest openSecureChannelRequest;
+ size_t offset = 0;
UA_StatusCode retval = UA_NodeId_decodeBinary(msg, &offset, &requestType);
-
if(retval != UA_STATUSCODE_GOOD) {
UA_NodeId_clear(&requestType);
UA_LOG_WARNING_CHANNEL(&server->config.logger, channel,
@@ -25150,11 +24607,12 @@ processOPN(UA_Server *server, UA_SecureChannel *channel,
UA_Server_closeSecureChannel(server, channel, UA_DIAGNOSTICEVENT_REJECT);
return retval;
}
- retval = UA_OpenSecureChannelRequest_decodeBinary(msg, &offset, &openSecureChannelRequest);
+ retval = UA_decodeBinaryInternal(msg, &offset, &openSecureChannelRequest,
+ &UA_TYPES[UA_TYPES_OPENSECURECHANNELREQUEST], NULL);
/* Error occurred */
if(retval != UA_STATUSCODE_GOOD ||
- requestType.identifier.numeric != UA_TYPES[UA_TYPES_OPENSECURECHANNELREQUEST].binaryEncodingId) {
+ !UA_NodeId_equal(&requestType, &UA_TYPES[UA_TYPES_OPENSECURECHANNELREQUEST].binaryEncodingId)) {
UA_NodeId_clear(&requestType);
UA_OpenSecureChannelRequest_clear(&openSecureChannelRequest);
UA_LOG_WARNING_CHANNEL(&server->config.logger, channel,
@@ -25190,84 +24648,18 @@ processOPN(UA_Server *server, UA_SecureChannel *channel,
return retval;
}
-static UA_StatusCode
-decryptProcessOPN(UA_Server *server, UA_SecureChannel *channel,
- UA_ByteString *msg) {
- UA_LOG_DEBUG_CHANNEL(&server->config.logger, channel, "Decrypt an OPN message");
-
- /* Skip the first header. We know length and message type. */
- size_t offset = UA_SECURE_CONVERSATION_MESSAGE_HEADER_LENGTH;
-
- /* Decode the asymmetric algorithm security header and call the callback
- * to perform checks. */
- UA_AsymmetricAlgorithmSecurityHeader asymHeader;
- UA_AsymmetricAlgorithmSecurityHeader_init(&asymHeader);
- UA_StatusCode retval =
- UA_AsymmetricAlgorithmSecurityHeader_decodeBinary(msg, &offset, &asymHeader);
- if(retval != UA_STATUSCODE_GOOD) {
- UA_LOG_WARNING_CHANNEL(&server->config.logger, channel,
- "Could not decode the OPN header");
- return retval;
- }
-
- /* Verify the certificate before creating the SecureChannel with it */
- if(asymHeader.senderCertificate.length > 0) {
- retval = server->config.certificateVerification.
- verifyCertificate(server->config.certificateVerification.context,
- &asymHeader.senderCertificate);
- if(retval != UA_STATUSCODE_GOOD) {
- UA_LOG_WARNING_CHANNEL(&server->config.logger, channel,
- "Could not verify the client's certificate");
- return retval;
- }
- }
-
- if(channel->state < UA_SECURECHANNELSTATE_OPEN) {
- retval = UA_Server_configSecureChannel(server, channel, &asymHeader);
- if(retval != UA_STATUSCODE_GOOD) {
- UA_AsymmetricAlgorithmSecurityHeader_clear(&asymHeader);
- return retval;
- }
- }
-
- retval = checkAsymHeader(channel, &asymHeader);
- UA_AsymmetricAlgorithmSecurityHeader_clear(&asymHeader);
- if(retval != UA_STATUSCODE_GOOD) {
- UA_LOG_WARNING_CHANNEL(&server->config.logger, channel,
- "Could not verify OPN header");
- return retval;
- }
-
- retval = decryptAndVerifyChunk(channel, &channel->securityPolicy->asymmetricModule.cryptoModule,
- UA_MESSAGETYPE_OPN, msg, offset);
- if(retval != UA_STATUSCODE_GOOD) {
- UA_LOG_WARNING_CHANNEL(&server->config.logger, channel,
- "Could not decrypt and verify the OPN payload");
- return retval;
- }
-
- /* Decode the sequence header */
- UA_SequenceHeader sequenceHeader;
- retval = UA_SequenceHeader_decodeBinary(msg, &offset, &sequenceHeader);
- if(retval != UA_STATUSCODE_GOOD)
- return retval;
-
-#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
- retval = processSequenceNumberAsym(channel, sequenceHeader.sequenceNumber);
- if(retval != UA_STATUSCODE_GOOD) {
- UA_LOG_WARNING_CHANNEL(&server->config.logger, channel,
- "Could not process the OPN message's sequence number");
- return retval;
- }
-#endif
-
- return processOPN(server, channel, sequenceHeader.requestId, msg, offset);
-}
-
/* The responseHeader must have the requestHandle already set */
UA_StatusCode
sendResponse(UA_Server *server, UA_Session *session, UA_SecureChannel *channel,
UA_UInt32 requestId, UA_Response *response, const UA_DataType *responseType) {
+ if(!channel)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ /* If the overall service call failed, answer with a ServiceFault */
+ if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD)
+ return sendServiceFault(channel, requestId, response->responseHeader.requestHandle,
+ response->responseHeader.serviceResult);
+
/* Prepare the ResponseHeader */
response->responseHeader.timestamp = UA_DateTime_now();
@@ -25278,8 +24670,8 @@ sendResponse(UA_Server *server, UA_Session *session, UA_SecureChannel *channel,
(unsigned)requestId, responseType->typeName);
#else
UA_LOG_DEBUG_SESSION(&server->config.logger, session,
- "Sending reponse for RequestId %u of type %" PRIi16,
- (unsigned)requestId, responseType->binaryEncodingId);
+ "Sending reponse for RequestId %u of type %" PRIu32,
+ (unsigned)requestId, responseType->binaryEncodingId.identifier.numeric);
#endif
} else {
#ifdef UA_ENABLE_TYPEDESCRIPTION
@@ -25288,8 +24680,8 @@ sendResponse(UA_Server *server, UA_Session *session, UA_SecureChannel *channel,
(unsigned)requestId, responseType->typeName);
#else
UA_LOG_DEBUG_CHANNEL(&server->config.logger, channel,
- "Sending reponse for RequestId %u of type %" PRIi16,
- (unsigned)requestId, responseType->binaryEncodingId);
+ "Sending reponse for RequestId %u of type %" PRIu32,
+ (unsigned)requestId, responseType->binaryEncodingId.identifier.numeric);
#endif
}
@@ -25300,12 +24692,12 @@ sendResponse(UA_Server *server, UA_Session *session, UA_SecureChannel *channel,
return retval;
/* Assert's required for clang-analyzer */
- UA_assert(mc.buf_pos == &mc.messageBuffer.data[UA_SECURE_MESSAGE_HEADER_LENGTH]);
+ UA_assert(mc.buf_pos == &mc.messageBuffer.data[UA_SECURECHANNEL_SYMMETRIC_HEADER_TOTALLENGTH]);
UA_assert(mc.buf_end <= &mc.messageBuffer.data[mc.messageBuffer.length]);
/* Encode the response type */
- UA_NodeId typeId = UA_NODEID_NUMERIC(0, responseType->binaryEncodingId);
- retval = UA_MessageContext_encode(&mc, &typeId, &UA_TYPES[UA_TYPES_NODEID]);
+ retval = UA_MessageContext_encode(&mc, &responseType->binaryEncodingId,
+ &UA_TYPES[UA_TYPES_NODEID]);
if(retval != UA_STATUSCODE_GOOD)
return retval;
@@ -25334,15 +24726,24 @@ getBoundSession(UA_Server *server, const UA_SecureChannel *channel,
continue;
UA_Session *current = (UA_Session*)sh;
/* Has the session timed out? */
- if(current->validTill < now)
+ if(current->validTill < now) {
+ server->serverDiagnosticsSummary.rejectedSessionCount++;
return UA_STATUSCODE_BADSESSIONCLOSED;
+ }
*session = current;
return UA_STATUSCODE_GOOD;
}
+ server->serverDiagnosticsSummary.rejectedSessionCount++;
+
/* Session exists on another SecureChannel. The CTT expect this error. */
- if(getSessionByToken(server, token))
+ UA_Session *tmpSession = getSessionByToken(server, token);
+ if(tmpSession) {
+#ifdef UA_ENABLE_DIAGNOSTICS
+ tmpSession->diagnostics.unauthorizedRequestCount++;
+#endif
return UA_STATUSCODE_BADSECURECHANNELIDINVALID;
+ }
return UA_STATUSCODE_GOOD;
}
@@ -25350,11 +24751,17 @@ getBoundSession(UA_Server *server, const UA_SecureChannel *channel,
static const UA_String securityPolicyNone =
UA_STRING_STATIC("http://opcfoundation.org/UA/SecurityPolicy#None");
+/* Returns a status of the SecureChannel. The detailed service status (usually
+ * part of the response) is set in the serviceResult argument. */
static UA_StatusCode
processMSGDecoded(UA_Server *server, UA_SecureChannel *channel, UA_UInt32 requestId,
UA_Service service, const UA_Request *request,
const UA_DataType *requestType, UA_Response *response,
- const UA_DataType *responseType, UA_Boolean sessionRequired) {
+ const UA_DataType *responseType, UA_Boolean sessionRequired,
+ size_t counterOffset) {
+ UA_Session *session = NULL;
+ UA_StatusCode channelRes = UA_STATUSCODE_GOOD;
+ UA_StatusCode serviceRes = UA_STATUSCODE_GOOD;
const UA_RequestHeader *requestHeader = &request->requestHeader;
/* If it is an unencrypted (#None) channel, only allow the discovery services */
@@ -25366,17 +24773,19 @@ processMSGDecoded(UA_Server *server, UA_SecureChannel *channel, UA_UInt32 reques
&& requestType != &UA_TYPES[UA_TYPES_FINDSERVERSONNETWORKREQUEST]
#endif
) {
- return sendServiceFault(channel, requestId, requestHeader->requestHandle,
- responseType, UA_STATUSCODE_BADSECURITYPOLICYREJECTED);
+ serviceRes = UA_STATUSCODE_BADSECURITYPOLICYREJECTED;
+ channelRes = sendServiceFault(channel, requestId, requestHeader->requestHandle,
+ UA_STATUSCODE_BADSECURITYPOLICYREJECTED);
+ goto update_statistics;
}
/* Session lifecycle services. */
if(requestType == &UA_TYPES[UA_TYPES_CREATESESSIONREQUEST] ||
requestType == &UA_TYPES[UA_TYPES_ACTIVATESESSIONREQUEST] ||
requestType == &UA_TYPES[UA_TYPES_CLOSESESSIONREQUEST]) {
- UA_LOCK(server->serviceMutex);
- ((UA_ChannelService)(uintptr_t)service)(server, channel, request, response);
- UA_UNLOCK(server->serviceMutex);
+ UA_LOCK(&server->serviceMutex);
+ ((UA_ChannelService)service)(server, channel, request, response);
+ UA_UNLOCK(&server->serviceMutex);
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
/* Store the authentication token so we can help fuzzing by setting
* these values in the next request automatically */
@@ -25385,17 +24794,24 @@ processMSGDecoded(UA_Server *server, UA_SecureChannel *channel, UA_UInt32 reques
UA_NodeId_copy(&res->authenticationToken, &unsafe_fuzz_authenticationToken);
}
#endif
- return sendResponse(server, NULL, channel, requestId, response, responseType);
+ serviceRes = response->responseHeader.serviceResult;
+ channelRes = sendResponse(server, NULL, channel, requestId, response, responseType);
+ goto update_statistics;
}
/* Get the Session bound to the SecureChannel (not necessarily activated) */
- UA_Session *session = NULL;
- UA_StatusCode retval = UA_STATUSCODE_GOOD;
if(!UA_NodeId_isNull(&requestHeader->authenticationToken)) {
- retval = getBoundSession(server, channel, &requestHeader->authenticationToken, &session);
- if(retval != UA_STATUSCODE_GOOD)
- return sendServiceFault(channel, requestId, requestHeader->requestHandle,
- responseType, retval);
+ UA_LOCK(&server->serviceMutex);
+ UA_StatusCode retval =
+ getBoundSession(server, channel,
+ &requestHeader->authenticationToken, &session);
+ UA_UNLOCK(&server->serviceMutex);
+ if(retval != UA_STATUSCODE_GOOD) {
+ serviceRes = response->responseHeader.serviceResult;
+ channelRes = sendServiceFault(channel, requestId,
+ requestHeader->requestHandle, retval);
+ goto update_statistics;
+ }
}
/* Set an anonymous, inactive session for services that need no session */
@@ -25408,11 +24824,13 @@ processMSGDecoded(UA_Server *server, UA_SecureChannel *channel, UA_UInt32 reques
requestType->typeName);
#else
UA_LOG_WARNING_CHANNEL(&server->config.logger, channel,
- "Service %" PRIi16 " refused without a valid session",
- requestType->binaryEncodingId);
+ "Service %" PRIu32 " refused without a valid session",
+ requestType->binaryEncodingId.identifier.numeric);
#endif
- return sendServiceFault(channel, requestId, requestHeader->requestHandle,
- responseType, UA_STATUSCODE_BADSESSIONIDINVALID);
+ serviceRes = UA_STATUSCODE_BADSESSIONIDINVALID;
+ channelRes = sendServiceFault(channel, requestId, requestHeader->requestHandle,
+ UA_STATUSCODE_BADSESSIONIDINVALID);
+ goto update_statistics;
}
UA_Session_init(&anonymousSession);
@@ -25431,17 +24849,19 @@ processMSGDecoded(UA_Server *server, UA_SecureChannel *channel, UA_UInt32 reques
requestType->typeName);
#else
UA_LOG_WARNING_SESSION(&server->config.logger, session,
- "Service %" PRIi16 " refused on a non-activated session",
- requestType->binaryEncodingId);
+ "Service %" PRIu32 " refused on a non-activated session",
+ requestType->binaryEncodingId.identifier.numeric);
#endif
if(session != &anonymousSession) {
- UA_LOCK(server->serviceMutex);
+ UA_LOCK(&server->serviceMutex);
UA_Server_removeSessionByToken(server, &session->header.authenticationToken,
UA_DIAGNOSTICEVENT_ABORT);
- UA_UNLOCK(server->serviceMutex);
+ UA_UNLOCK(&server->serviceMutex);
}
- return sendServiceFault(channel, requestId, requestHeader->requestHandle,
- responseType, UA_STATUSCODE_BADSESSIONNOTACTIVATED);
+ serviceRes = UA_STATUSCODE_BADSESSIONNOTACTIVATED;
+ channelRes = sendServiceFault(channel, requestId, requestHeader->requestHandle,
+ UA_STATUSCODE_BADSESSIONNOTACTIVATED);
+ goto update_statistics;
}
/* Update the session lifetime */
@@ -25450,10 +24870,11 @@ processMSGDecoded(UA_Server *server, UA_SecureChannel *channel, UA_UInt32 reques
#ifdef UA_ENABLE_SUBSCRIPTIONS
/* The publish request is not answered immediately */
if(requestType == &UA_TYPES[UA_TYPES_PUBLISHREQUEST]) {
- UA_LOCK(server->serviceMutex);
- Service_Publish(server, session, &request->publishRequest, requestId);
- UA_UNLOCK(server->serviceMutex);
- return UA_STATUSCODE_GOOD;
+ UA_LOCK(&server->serviceMutex);
+ serviceRes = Service_Publish(server, session, &request->publishRequest, requestId);
+ /* No channelRes due to the async response */
+ UA_UNLOCK(&server->serviceMutex);
+ goto update_statistics;
}
#endif
@@ -25461,30 +24882,59 @@ processMSGDecoded(UA_Server *server, UA_SecureChannel *channel, UA_UInt32 reques
/* The call request might not be answered immediately */
if(requestType == &UA_TYPES[UA_TYPES_CALLREQUEST]) {
UA_Boolean finished = true;
- UA_LOCK(server->serviceMutex);
+ UA_LOCK(&server->serviceMutex);
Service_CallAsync(server, session, requestId, &request->callRequest,
&response->callResponse, &finished);
- UA_UNLOCK(server->serviceMutex);
-
- /* Async method calls remain. Don't send a response now */
- if(!finished)
- return UA_STATUSCODE_GOOD;
+ UA_UNLOCK(&server->serviceMutex);
- /* We are done here */
- return sendResponse(server, session, channel, requestId, response, responseType);
+ /* Async method calls remain. Don't send a response now. In case we have
+ * an async call, count as a "good" request for the diagnostics
+ * statistic. */
+ if(UA_LIKELY(finished)) {
+ serviceRes = response->responseHeader.serviceResult;
+ channelRes = sendResponse(server, session, channel,
+ requestId, response, responseType);
+ }
+ goto update_statistics;
}
#endif
- /* Dispatch the synchronous service call and send the response */
- UA_LOCK(server->serviceMutex);
+ /* Execute the synchronous service call */
+ UA_LOCK(&server->serviceMutex);
service(server, session, request, response);
- UA_UNLOCK(server->serviceMutex);
- return sendResponse(server, session, channel, requestId, response, responseType);
+ UA_UNLOCK(&server->serviceMutex);
+
+ /* Send the response */
+ serviceRes = response->responseHeader.serviceResult;
+ channelRes = sendResponse(server, session, channel, requestId, response, responseType);
+
+ /* Update the diagnostics statistics */
+ update_statistics:
+#ifdef UA_ENABLE_DIAGNOSTICS
+ if(session && session != &server->adminSession) {
+ session->diagnostics.totalRequestCount.totalCount++;
+ if(serviceRes != UA_STATUSCODE_GOOD)
+ session->diagnostics.totalRequestCount.errorCount++;
+ if(counterOffset != 0) {
+ UA_ServiceCounterDataType *serviceCounter = (UA_ServiceCounterDataType*)
+ (((uintptr_t)&session->diagnostics) + counterOffset);
+ serviceCounter->totalCount++;
+ if(serviceRes != UA_STATUSCODE_GOOD)
+ serviceCounter->errorCount++;
+ }
+ }
+#else
+ (void)serviceRes; /* Pacify compiler warnings */
+#endif
+
+ return channelRes;
}
static UA_StatusCode
processMSG(UA_Server *server, UA_SecureChannel *channel,
UA_UInt32 requestId, const UA_ByteString *msg) {
+ if(channel->state != UA_SECURECHANNELSTATE_OPEN)
+ return UA_STATUSCODE_BADINTERNALERROR;
/* Decode the nodeid */
size_t offset = 0;
UA_NodeId requestTypeId;
@@ -25502,12 +24952,14 @@ processMSG(UA_Server *server, UA_SecureChannel *channel,
UA_Boolean sessionRequired = true;
const UA_DataType *requestType = NULL;
const UA_DataType *responseType = NULL;
+ size_t counterOffset = 0;
getServicePointers(requestTypeId.identifier.numeric, &requestType,
- &responseType, &service, &sessionRequired);
+ &responseType, &service, &sessionRequired, &counterOffset);
if(!requestType) {
- if(requestTypeId.identifier.numeric == 787) {
+ if(requestTypeId.identifier.numeric ==
+ UA_NS0ID_CREATESUBSCRIPTIONREQUEST_ENCODING_DEFAULTBINARY) {
UA_LOG_INFO_CHANNEL(&server->config.logger, channel,
- "Client requested a subscription, " \
+ "Client requested a subscription, "
"but those are not enabled in the build");
} else {
UA_LOG_INFO_CHANNEL(&server->config.logger, channel,
@@ -25522,7 +24974,8 @@ processMSG(UA_Server *server, UA_SecureChannel *channel,
/* Decode the request */
UA_Request request;
- retval = UA_decodeBinary(msg, &offset, &request, requestType, server->config.customDataTypes);
+ retval = UA_decodeBinaryInternal(msg, &offset, &request,
+ requestType, server->config.customDataTypes);
if(retval != UA_STATUSCODE_GOOD) {
UA_LOG_DEBUG_CHANNEL(&server->config.logger, channel,
"Could not decode the request with StatusCode %s",
@@ -25540,7 +24993,7 @@ processMSG(UA_Server *server, UA_SecureChannel *channel,
"See the 'verifyRequestTimestamp' setting.");
if(server->config.verifyRequestTimestamp <= UA_RULEHANDLING_ABORT) {
retval = sendServiceFault(channel, requestId, requestHeader->requestHandle,
- responseType, UA_STATUSCODE_BADINVALIDTIMESTAMP);
+ UA_STATUSCODE_BADINVALIDTIMESTAMP);
UA_clear(&request, requestType);
return retval;
}
@@ -25550,9 +25003,11 @@ processMSG(UA_Server *server, UA_SecureChannel *channel,
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
/* Set the authenticationToken from the create session request to help
* fuzzing cover more lines */
- UA_NodeId_clear(&requestHeader->authenticationToken);
- if(!UA_NodeId_isNull(&unsafe_fuzz_authenticationToken))
+ if(!UA_NodeId_isNull(&unsafe_fuzz_authenticationToken) &&
+ !UA_NodeId_isNull(&requestHeader->authenticationToken)) {
+ UA_NodeId_clear(&requestHeader->authenticationToken);
UA_NodeId_copy(&unsafe_fuzz_authenticationToken, &requestHeader->authenticationToken);
+ }
#endif
/* Prepare the respone and process the request */
@@ -25560,7 +25015,7 @@ processMSG(UA_Server *server, UA_SecureChannel *channel,
UA_init(&response, responseType);
response.responseHeader.requestHandle = requestHeader->requestHandle;
retval = processMSGDecoded(server, channel, requestId, service, &request, requestType,
- &response, responseType, sessionRequired);
+ &response, responseType, sessionRequired, counterOffset);
/* Clean up */
UA_clear(&request, requestType);
@@ -25569,7 +25024,7 @@ processMSG(UA_Server *server, UA_SecureChannel *channel,
}
/* Takes decoded messages starting at the nodeid of the content type. */
-static void
+static UA_StatusCode
processSecureChannelMessage(void *application, UA_SecureChannel *channel,
UA_MessageType messagetype, UA_UInt32 requestId,
UA_ByteString *message) {
@@ -25583,7 +25038,7 @@ processSecureChannelMessage(void *application, UA_SecureChannel *channel,
break;
case UA_MESSAGETYPE_OPN:
UA_LOG_TRACE_CHANNEL(&server->config.logger, channel, "Process an OPN message");
- retval = decryptProcessOPN(server, channel, message);
+ retval = processOPN(server, channel, requestId, message);
break;
case UA_MESSAGETYPE_MSG:
UA_LOG_TRACE_CHANNEL(&server->config.logger, channel, "Process a MSG");
@@ -25603,7 +25058,7 @@ processSecureChannelMessage(void *application, UA_SecureChannel *channel,
UA_LOG_INFO_CHANNEL(&server->config.logger, channel,
"Processing the message failed. Channel already closed "
"with StatusCode %s. ", UA_StatusCode_name(retval));
- return;
+ return retval;
}
UA_LOG_INFO_CHANNEL(&server->config.logger, channel,
@@ -25627,6 +25082,8 @@ processSecureChannelMessage(void *application, UA_SecureChannel *channel,
break;
}
}
+
+ return retval;
}
void
@@ -25673,31 +25130,13 @@ UA_Server_processBinaryMessage(UA_Server *server, UA_Connection *connection,
connection->close(connection);
}
-#if UA_MULTITHREADING >= 200
-static void
-deleteConnection(UA_Server *server, UA_Connection *connection) {
- connection->free(connection);
-}
-#endif
-
void
UA_Server_removeConnection(UA_Server *server, UA_Connection *connection) {
UA_Connection_detachSecureChannel(connection);
-#if UA_MULTITHREADING >= 200
- UA_DelayedCallback *dc = (UA_DelayedCallback*)UA_malloc(sizeof(UA_DelayedCallback));
- if(!dc)
- return; /* Malloc cannot fail on OS's that support multithreading. They
- * rather kill the process. */
- dc->callback = (UA_ApplicationCallback)deleteConnection;
- dc->application = server;
- dc->data = connection;
- UA_WorkQueue_enqueueDelayed(&server->workQueue, dc);
-#else
connection->free(connection);
-#endif
}
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/src/server/ua_server_utils.c" ***********************************/
+/**** amalgamated original file "/src/server/ua_server_utils.c" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -25712,109 +25151,29 @@ UA_Server_removeConnection(UA_Server *server, UA_Connection *connection) {
*/
-#define UA_MAX_TREE_RECURSE 50 /* How deep up/down the tree do we recurse at most? */
+const UA_DataType *
+UA_Server_findDataType(UA_Server *server, const UA_NodeId *typeId) {
+ return UA_findDataTypeWithCustom(typeId, server->config.customDataTypes);
+}
/********************************/
/* Information Model Operations */
/********************************/
-/* Keeps track of already visited nodes to detect circular references */
-struct ref_history {
- struct ref_history *parent; /* the previous element */
- const UA_NodeId *id; /* the id of the node at this depth */
- UA_UInt16 depth;
-};
-
-static UA_Boolean
-isNodeInTreeNoCircular(UA_Server *server, const UA_NodeId *leafNode, const UA_NodeId *nodeToFind,
- struct ref_history *visitedRefs, const UA_NodeId *referenceTypeIds,
- size_t referenceTypeIdsSize) {
- if(UA_NodeId_equal(nodeToFind, leafNode))
- return true;
-
- if(visitedRefs->depth >= UA_MAX_TREE_RECURSE)
- return false;
-
- const UA_Node *node = UA_NODESTORE_GET(server, leafNode);
- if(!node)
- return false;
-
- for(size_t i = 0; i < node->referencesSize; ++i) {
- UA_NodeReferenceKind *refs = &node->references[i];
- /* Search upwards in the tree */
- if(!refs->isInverse)
- continue;
-
- /* Consider only the indicated reference types */
- UA_Boolean match = false;
- for(size_t j = 0; j < referenceTypeIdsSize; ++j) {
- if(UA_NodeId_equal(&refs->referenceTypeId, &referenceTypeIds[j])) {
- match = true;
- break;
- }
- }
- if(!match)
- continue;
-
- /* Match the targets or recurse */
- for(size_t j = 0; j < refs->refTargetsSize; ++j) {
- /* Check if we already have seen the referenced node and skip to
- * avoid endless recursion. Do this only at every 5th depth to save
- * effort. Circular dependencies are rare and forbidden for most
- * reference types. */
- if(visitedRefs->depth % 5 == 4) {
- struct ref_history *last = visitedRefs;
- UA_Boolean skip = false;
- while(!skip && last) {
- if(UA_NodeId_equal(last->id, &refs->refTargets[j].targetId.nodeId))
- skip = true;
- last = last->parent;
- }
- if(skip)
- continue;
- }
-
- /* Stack-allocate the visitedRefs structure for the next depth */
- struct ref_history nextVisitedRefs = {visitedRefs, &refs->refTargets[j].targetId.nodeId,
- (UA_UInt16)(visitedRefs->depth+1)};
-
- /* Recurse */
- UA_Boolean foundRecursive =
- isNodeInTreeNoCircular(server, &refs->refTargets[j].targetId.nodeId, nodeToFind,
- &nextVisitedRefs, referenceTypeIds, referenceTypeIdsSize);
- if(foundRecursive) {
- UA_NODESTORE_RELEASE(server, node);
- return true;
- }
- }
- }
-
- UA_NODESTORE_RELEASE(server, node);
- return false;
-}
-
-UA_Boolean
-isNodeInTree(UA_Server *server, const UA_NodeId *leafNode, const UA_NodeId *nodeToFind,
- const UA_NodeId *referenceTypeIds, size_t referenceTypeIdsSize) {
- struct ref_history visitedRefs = {NULL, leafNode, 0};
- return isNodeInTreeNoCircular(server, leafNode, nodeToFind, &visitedRefs,
- referenceTypeIds, referenceTypeIdsSize);
-}
-
const UA_Node *
-getNodeType(UA_Server *server, const UA_Node *node) {
+getNodeType(UA_Server *server, const UA_NodeHead *head) {
/* The reference to the parent is different for variable and variabletype */
- UA_NodeId parentRef;
+ UA_Byte parentRefIndex;
UA_Boolean inverse;
UA_NodeClass typeNodeClass;
- switch(node->nodeClass) {
+ switch(head->nodeClass) {
case UA_NODECLASS_OBJECT:
- parentRef = UA_NODEID_NUMERIC(0, UA_NS0ID_HASTYPEDEFINITION);
+ parentRefIndex = UA_REFERENCETYPEINDEX_HASTYPEDEFINITION;
inverse = false;
typeNodeClass = UA_NODECLASS_OBJECTTYPE;
break;
case UA_NODECLASS_VARIABLE:
- parentRef = UA_NODEID_NUMERIC(0, UA_NS0ID_HASTYPEDEFINITION);
+ parentRefIndex = UA_REFERENCETYPEINDEX_HASTYPEDEFINITION;
inverse = false;
typeNodeClass = UA_NODECLASS_VARIABLETYPE;
break;
@@ -25822,69 +25181,72 @@ getNodeType(UA_Server *server, const UA_Node *node) {
case UA_NODECLASS_VARIABLETYPE:
case UA_NODECLASS_REFERENCETYPE:
case UA_NODECLASS_DATATYPE:
- parentRef = UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE);
+ parentRefIndex = UA_REFERENCETYPEINDEX_HASSUBTYPE;
inverse = true;
- typeNodeClass = node->nodeClass;
+ typeNodeClass = head->nodeClass;
break;
default:
return NULL;
}
/* Return the first matching candidate */
- for(size_t i = 0; i < node->referencesSize; ++i) {
- if(node->references[i].isInverse != inverse)
- continue;
- if(!UA_NodeId_equal(&node->references[i].referenceTypeId, &parentRef))
+ for(size_t i = 0; i < head->referencesSize; ++i) {
+ UA_NodeReferenceKind *rk = &head->references[i];
+ if(rk->isInverse != inverse)
continue;
- UA_assert(node->references[i].refTargetsSize> 0);
- const UA_NodeId *targetId = &node->references[i].refTargets[0].targetId.nodeId;
- const UA_Node *type = UA_NODESTORE_GET(server, targetId);
- if(!type)
+ if(rk->referenceTypeIndex != parentRefIndex)
continue;
- if(type->nodeClass == typeNodeClass)
- return type;
- UA_NODESTORE_RELEASE(server, type);
+
+ const UA_ReferenceTarget *t = NULL;
+ while((t = UA_NodeReferenceKind_iterate(rk, t))) {
+ const UA_Node *type = UA_NODESTORE_GETFROMREF(server, t->targetId);
+ if(!type)
+ continue;
+ if(type->head.nodeClass == typeNodeClass)
+ return type; /* Don't release the node that is returned */
+ UA_NODESTORE_RELEASE(server, type);
+ }
}
return NULL;
}
UA_Boolean
-UA_Node_hasSubTypeOrInstances(const UA_Node *node) {
- const UA_NodeId hasSubType = UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE);
- const UA_NodeId hasTypeDefinition = UA_NODEID_NUMERIC(0, UA_NS0ID_HASTYPEDEFINITION);
- for(size_t i = 0; i < node->referencesSize; ++i) {
- if(node->references[i].isInverse == false &&
- UA_NodeId_equal(&node->references[i].referenceTypeId, &hasSubType))
+UA_Node_hasSubTypeOrInstances(const UA_NodeHead *head) {
+ for(size_t i = 0; i < head->referencesSize; ++i) {
+ if(head->references[i].isInverse == false &&
+ head->references[i].referenceTypeIndex == UA_REFERENCETYPEINDEX_HASSUBTYPE)
return true;
- if(node->references[i].isInverse == true &&
- UA_NodeId_equal(&node->references[i].referenceTypeId, &hasTypeDefinition))
+ if(head->references[i].isInverse == true &&
+ head->references[i].referenceTypeIndex == UA_REFERENCETYPEINDEX_HASTYPEDEFINITION)
return true;
}
return false;
}
-static const UA_NodeId hasInterfaceNodeId =
- {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_HASINTERFACE}};
-
UA_StatusCode
getParentTypeAndInterfaceHierarchy(UA_Server *server, const UA_NodeId *typeNode,
UA_NodeId **typeHierarchy, size_t *typeHierarchySize) {
+ UA_ReferenceTypeSet reftypes_subtype =
+ UA_REFTYPESET(UA_REFERENCETYPEINDEX_HASSUBTYPE);
UA_ExpandedNodeId *subTypes = NULL;
size_t subTypesSize = 0;
- UA_StatusCode retval = browseRecursive(server, 1, typeNode, 1, &subtypeId,
- UA_BROWSEDIRECTION_INVERSE, false,
- &subTypesSize, &subTypes);
+ UA_StatusCode retval = browseRecursive(server, 1, typeNode,
+ UA_BROWSEDIRECTION_INVERSE,
+ &reftypes_subtype, UA_NODECLASS_UNSPECIFIED,
+ false, &subTypesSize, &subTypes);
if(retval != UA_STATUSCODE_GOOD)
return retval;
UA_assert(subTypesSize < 1000);
+ UA_ReferenceTypeSet reftypes_interface =
+ UA_REFTYPESET(UA_REFERENCETYPEINDEX_HASINTERFACE);
UA_ExpandedNodeId *interfaces = NULL;
size_t interfacesSize = 0;
- retval = browseRecursive(server, 1, typeNode, 1, &hasInterfaceNodeId,
- UA_BROWSEDIRECTION_FORWARD, false,
- &interfacesSize, &interfaces);
+ retval = browseRecursive(server, 1, typeNode, UA_BROWSEDIRECTION_FORWARD,
+ &reftypes_interface, UA_NODECLASS_UNSPECIFIED,
+ false, &interfacesSize, &interfaces);
if(retval != UA_STATUSCODE_GOOD) {
UA_Array_delete(subTypes, subTypesSize, &UA_TYPES[UA_TYPES_NODEID]);
return retval;
@@ -25927,6 +25289,124 @@ getParentTypeAndInterfaceHierarchy(UA_Server *server, const UA_NodeId *typeNode,
return UA_STATUSCODE_GOOD;
}
+UA_StatusCode
+getAllInterfaceChildNodeIds(UA_Server *server, const UA_NodeId *objectNode,
+ const UA_NodeId *objectTypeNode,
+ UA_NodeId **interfaceChildNodes,
+ size_t *interfaceChildNodesSize) {
+ if(interfaceChildNodesSize == NULL || interfaceChildNodes == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+ *interfaceChildNodesSize = 0;
+ *interfaceChildNodes = NULL;
+
+ UA_ExpandedNodeId *hasInterfaceCandidates = NULL;
+ size_t hasInterfaceCandidatesSize = 0;
+ UA_ReferenceTypeSet reftypes_subtype =
+ UA_REFTYPESET(UA_REFERENCETYPEINDEX_HASSUBTYPE);
+
+ UA_StatusCode retval =
+ browseRecursive(server, 1, objectTypeNode, UA_BROWSEDIRECTION_INVERSE,
+ &reftypes_subtype, UA_NODECLASS_OBJECTTYPE,
+ true, &hasInterfaceCandidatesSize,
+ &hasInterfaceCandidates);
+
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+
+ /* The interface could also have been added manually before calling UA_Server_addNode_finish
+ * This can be handled by adding the object node as a start node for the HasInterface lookup */
+ UA_ExpandedNodeId *resizedHasInterfaceCandidates = (UA_ExpandedNodeId*)
+ UA_realloc(hasInterfaceCandidates,
+ (hasInterfaceCandidatesSize + 1) * sizeof(UA_ExpandedNodeId));
+
+ if(!resizedHasInterfaceCandidates) {
+ if(hasInterfaceCandidates)
+ UA_Array_delete(hasInterfaceCandidates, hasInterfaceCandidatesSize,
+ &UA_TYPES[UA_TYPES_EXPANDEDNODEID]);
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ }
+
+ hasInterfaceCandidates = resizedHasInterfaceCandidates;
+ hasInterfaceCandidatesSize += 1;
+ UA_ExpandedNodeId_init(&hasInterfaceCandidates[hasInterfaceCandidatesSize - 1]);
+
+ UA_ExpandedNodeId_init(&hasInterfaceCandidates[hasInterfaceCandidatesSize - 1]);
+ UA_NodeId_copy(objectNode, &hasInterfaceCandidates[hasInterfaceCandidatesSize - 1].nodeId);
+
+ size_t outputIndex = 0;
+
+ for(size_t i = 0; i < hasInterfaceCandidatesSize; ++i) {
+ UA_ReferenceTypeSet reftypes_interface =
+ UA_REFTYPESET(UA_REFERENCETYPEINDEX_HASINTERFACE);
+ UA_ExpandedNodeId *interfaceChildren = NULL;
+ size_t interfacesChildrenSize = 0;
+ retval = browseRecursive(server, 1, &hasInterfaceCandidates[i].nodeId,
+ UA_BROWSEDIRECTION_FORWARD,
+ &reftypes_interface, UA_NODECLASS_OBJECTTYPE,
+ false, &interfacesChildrenSize, &interfaceChildren);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_Array_delete(hasInterfaceCandidates, hasInterfaceCandidatesSize,
+ &UA_TYPES[UA_TYPES_EXPANDEDNODEID]);
+ if(*interfaceChildNodesSize) {
+ UA_Array_delete(*interfaceChildNodes, *interfaceChildNodesSize,
+ &UA_TYPES[UA_TYPES_NODEID]);
+ *interfaceChildNodesSize = 0;
+ }
+ return retval;
+ }
+
+ UA_assert(interfacesChildrenSize < 1000);
+
+ if(interfacesChildrenSize == 0) {
+ continue;
+ }
+
+ if(!*interfaceChildNodes) {
+ *interfaceChildNodes = (UA_NodeId*)
+ UA_calloc(interfacesChildrenSize, sizeof(UA_NodeId));
+ *interfaceChildNodesSize = interfacesChildrenSize;
+
+ if(!*interfaceChildNodes) {
+ UA_Array_delete(interfaceChildren, interfacesChildrenSize,
+ &UA_TYPES[UA_TYPES_EXPANDEDNODEID]);
+ UA_Array_delete(hasInterfaceCandidates, hasInterfaceCandidatesSize,
+ &UA_TYPES[UA_TYPES_EXPANDEDNODEID]);
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ }
+ } else {
+ UA_NodeId *resizedInterfaceChildNodes = (UA_NodeId*)
+ UA_realloc(*interfaceChildNodes,
+ ((*interfaceChildNodesSize + interfacesChildrenSize) * sizeof(UA_NodeId)));
+
+ if(!resizedInterfaceChildNodes) {
+ UA_Array_delete(hasInterfaceCandidates, hasInterfaceCandidatesSize,
+ &UA_TYPES[UA_TYPES_EXPANDEDNODEID]);
+ UA_Array_delete(interfaceChildren, interfacesChildrenSize,
+ &UA_TYPES[UA_TYPES_EXPANDEDNODEID]);
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ }
+
+ const size_t oldSize = *interfaceChildNodesSize;
+ *interfaceChildNodesSize += interfacesChildrenSize;
+ *interfaceChildNodes = resizedInterfaceChildNodes;
+
+ for(size_t j = oldSize; j < *interfaceChildNodesSize; ++j)
+ UA_NodeId_init(&(*interfaceChildNodes)[j]);
+ }
+
+ for(size_t j = 0; j < interfacesChildrenSize; j++) {
+ (*interfaceChildNodes)[outputIndex++] = interfaceChildren[j].nodeId;
+ }
+
+ UA_assert(*interfaceChildNodesSize < 1000);
+ UA_Array_delete(interfaceChildren, interfacesChildrenSize, &UA_TYPES[UA_TYPES_EXPANDEDNODEID]);
+ }
+
+ UA_Array_delete(hasInterfaceCandidates, hasInterfaceCandidatesSize, &UA_TYPES[UA_TYPES_EXPANDEDNODEID]);
+
+ return UA_STATUSCODE_GOOD;
+}
+
/* For mulithreading: make a copy of the node, edit and replace.
* For singlethreading: edit the original */
UA_StatusCode
@@ -26083,7 +25563,7 @@ const UA_ViewAttributes UA_ViewAttributes_default = {
};
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/src/server/ua_server_discovery.c" ***********************************/
+/**** amalgamated original file "/src/server/ua_server_discovery.c" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -26132,31 +25612,31 @@ register_server_with_discovery_server(UA_Server *server,
request.server.serverNames = &server->config.applicationDescription.applicationName;
request.server.serverNamesSize = 1;
- /* Copy the discovery urls from the server config and the network layers*/
+ /* Mirror the discovery urls from the server config and the network layers */
size_t config_discurls = server->config.applicationDescription.discoveryUrlsSize;
size_t nl_discurls = server->config.networkLayersSize;
size_t total_discurls = config_discurls + nl_discurls;
- UA_STACKARRAY(UA_String, urlsBuf, total_discurls);
- request.server.discoveryUrls = urlsBuf;
- request.server.discoveryUrlsSize = total_discurls;
+ request.server.discoveryUrls = (UA_String*)
+ UA_Array_new(total_discurls, &UA_TYPES[UA_TYPES_STRING]);
+ if(!request.server.discoveryUrls)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
for(size_t i = 0; i < config_discurls; ++i)
request.server.discoveryUrls[i] = server->config.applicationDescription.discoveryUrls[i];
-
/* TODO: Add nl only if discoveryUrl not already present */
for(size_t i = 0; i < nl_discurls; ++i) {
UA_ServerNetworkLayer *nl = &server->config.networkLayers[i];
request.server.discoveryUrls[config_discurls + i] = nl->discoveryUrl;
}
+ request.server.discoveryUrlsSize = total_discurls;
#ifdef UA_ENABLE_DISCOVERY_MULTICAST
request.discoveryConfigurationSize = 1;
request.discoveryConfiguration = UA_ExtensionObject_new();
- UA_ExtensionObject_init(&request.discoveryConfiguration[0]);
// Set to NODELETE so that we can just use a pointer to the mdns config
- request.discoveryConfiguration[0].encoding = UA_EXTENSIONOBJECT_DECODED_NODELETE;
- request.discoveryConfiguration[0].content.decoded.type = &UA_TYPES[UA_TYPES_MDNSDISCOVERYCONFIGURATION];
- request.discoveryConfiguration[0].content.decoded.data = &server->config.discovery.mdns;
+ UA_ExtensionObject_setValueNoDelete(request.discoveryConfiguration,
+ &server->config.mdnsConfig,
+ &UA_TYPES[UA_TYPES_MDNSDISCOVERYCONFIGURATION]);
#endif
// First try with RegisterServer2, if that isn't implemented, use RegisterServer
@@ -26169,8 +25649,8 @@ register_server_with_discovery_server(UA_Server *server,
UA_Array_delete(request.discoveryConfiguration,
request.discoveryConfigurationSize,
&UA_TYPES[UA_TYPES_EXTENSIONOBJECT]);
- request.discoveryConfiguration = NULL;
- request.discoveryConfigurationSize = 0;
+ if(total_discurls > 0)
+ UA_free(request.server.discoveryUrls);
if(serviceResult == UA_STATUSCODE_BADNOTIMPLEMENTED ||
serviceResult == UA_STATUSCODE_BADSERVICEUNSUPPORTED) {
@@ -26204,25 +25684,25 @@ register_server_with_discovery_server(UA_Server *server,
UA_StatusCode
UA_Server_register_discovery(UA_Server *server, UA_Client *client,
const char* semaphoreFilePath) {
- UA_LOCK(server->serviceMutex);
+ UA_LOCK(&server->serviceMutex);
UA_StatusCode retval = register_server_with_discovery_server(server, client,
false, semaphoreFilePath);
- UA_UNLOCK(server->serviceMutex);
+ UA_UNLOCK(&server->serviceMutex);
return retval;
}
UA_StatusCode
UA_Server_unregister_discovery(UA_Server *server, UA_Client *client) {
- UA_LOCK(server->serviceMutex);
+ UA_LOCK(&server->serviceMutex);
UA_StatusCode retval = register_server_with_discovery_server(server, client,
true, NULL);
- UA_UNLOCK(server->serviceMutex);
+ UA_UNLOCK(&server->serviceMutex);
return retval;
}
#endif /* UA_ENABLE_DISCOVERY */
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/src/server/ua_server_async.c" ***********************************/
+/**** amalgamated original file "/src/server/ua_server_async.c" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -26247,9 +25727,11 @@ UA_AsyncManager_sendAsyncResponse(UA_AsyncManager *am, UA_Server *server,
UA_AsyncResponse *ar) {
/* Get the session */
UA_StatusCode res = UA_STATUSCODE_GOOD;
- UA_LOCK(server->serviceMutex);
+ UA_LOCK(&server->serviceMutex);
UA_Session* session = UA_Server_getSessionById(server, &ar->sessionId);
- UA_UNLOCK(server->serviceMutex);
+ UA_UNLOCK(&server->serviceMutex);
+ UA_SecureChannel* channel = NULL;
+ UA_ResponseHeader *responseHeader = NULL;
if(!session) {
res = UA_STATUSCODE_BADSESSIONIDINVALID;
UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
@@ -26258,7 +25740,7 @@ UA_AsyncManager_sendAsyncResponse(UA_AsyncManager *am, UA_Server *server,
}
/* Check the channel */
- UA_SecureChannel* channel = session->header.channel;
+ channel = session->header.channel;
if(!channel) {
res = UA_STATUSCODE_BADSECURECHANNELCLOSED;
UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
@@ -26267,7 +25749,7 @@ UA_AsyncManager_sendAsyncResponse(UA_AsyncManager *am, UA_Server *server,
}
/* Okay, here we go, send the UA_CallResponse */
- UA_ResponseHeader *responseHeader = (UA_ResponseHeader*)
+ responseHeader = (UA_ResponseHeader*)
&ar->response.callResponse.responseHeader;
responseHeader->requestHandle = ar->requestHandle;
res = sendResponse(server, session, channel, ar->requestId,
@@ -26311,11 +25793,11 @@ static void
processAsyncResults(UA_Server *server, void *data) {
UA_AsyncManager *am = &server->asyncManager;
while(true) {
- UA_LOCK(am->queueLock);
+ UA_LOCK(&am->queueLock);
UA_AsyncOperation *ao = TAILQ_FIRST(&am->resultQueue);
if(ao)
TAILQ_REMOVE(&am->resultQueue, ao, pointers);
- UA_UNLOCK(am->queueLock);
+ UA_UNLOCK(&am->queueLock);
if(!ao)
break;
UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER,
@@ -26336,7 +25818,7 @@ checkTimeouts(UA_Server *server, void *_) {
UA_AsyncManager *am = &server->asyncManager;
const UA_DateTime tNow = UA_DateTime_now();
- UA_LOCK(am->queueLock);
+ UA_LOCK(&am->queueLock);
/* Loop over the queue of dispatched ops */
UA_AsyncOperation *op = NULL, *op_tmp = NULL;
@@ -26367,7 +25849,7 @@ checkTimeouts(UA_Server *server, void *_) {
"Operation was removed due to a timeout");
}
- UA_UNLOCK(am->queueLock);
+ UA_UNLOCK(&am->queueLock);
/* Integrate async results and send out complete responses */
processAsyncResults(server, NULL);
@@ -26380,7 +25862,7 @@ UA_AsyncManager_init(UA_AsyncManager *am, UA_Server *server) {
TAILQ_INIT(&am->newQueue);
TAILQ_INIT(&am->dispatchedQueue);
TAILQ_INIT(&am->resultQueue);
- UA_LOCK_INIT(am->queueLock);
+ UA_LOCK_INIT(&am->queueLock);
/* Add a regular callback for cleanup and sending finished responses at a
* 100s interval. */
@@ -26390,25 +25872,25 @@ UA_AsyncManager_init(UA_AsyncManager *am, UA_Server *server) {
void
UA_AsyncManager_clear(UA_AsyncManager *am, UA_Server *server) {
- UA_Server_removeCallback(server, am->checkTimeoutCallbackId);
+ removeCallback(server, am->checkTimeoutCallbackId);
- UA_AsyncOperation *ar;
+ UA_AsyncOperation *ar, *ar_tmp;
/* Clean up queues */
- UA_LOCK(am->queueLock);
- while((ar = TAILQ_FIRST(&am->newQueue))) {
- TAILQ_REMOVE(&am->resultQueue, ar, pointers);
+ UA_LOCK(&am->queueLock);
+ TAILQ_FOREACH_SAFE(ar, &am->newQueue, pointers, ar_tmp) {
+ TAILQ_REMOVE(&am->newQueue, ar, pointers);
UA_AsyncOperation_delete(ar);
}
- while((ar = TAILQ_FIRST(&am->dispatchedQueue))) {
- TAILQ_REMOVE(&am->resultQueue, ar, pointers);
+ TAILQ_FOREACH_SAFE(ar, &am->dispatchedQueue, pointers, ar_tmp) {
+ TAILQ_REMOVE(&am->dispatchedQueue, ar, pointers);
UA_AsyncOperation_delete(ar);
}
- while((ar = TAILQ_FIRST(&am->resultQueue))) {
+ TAILQ_FOREACH_SAFE(ar, &am->resultQueue, pointers, ar_tmp) {
TAILQ_REMOVE(&am->resultQueue, ar, pointers);
UA_AsyncOperation_delete(ar);
}
- UA_UNLOCK(am->queueLock);
+ UA_UNLOCK(&am->queueLock);
/* Remove responses */
UA_AsyncResponse *current, *temp;
@@ -26417,7 +25899,7 @@ UA_AsyncManager_clear(UA_AsyncManager *am, UA_Server *server) {
}
/* Delete all locks */
- UA_LOCK_DESTROY(am->queueLock);
+ UA_LOCK_DESTROY(&am->queueLock);
}
UA_StatusCode
@@ -26491,11 +25973,11 @@ UA_AsyncManager_createAsyncOp(UA_AsyncManager *am, UA_Server *server,
ao->index = opIndex;
ao->parent = ar;
- UA_LOCK(am->queueLock);
+ UA_LOCK(&am->queueLock);
TAILQ_INSERT_TAIL(&am->newQueue, ao, pointers);
am->opsCount++;
ar->opCountdown++;
- UA_UNLOCK(am->queueLock);
+ UA_UNLOCK(&am->queueLock);
if(server->config.asyncOperationNotifyCallback)
server->config.asyncOperationNotifyCallback(server);
@@ -26512,7 +25994,7 @@ UA_Server_getAsyncOperationNonBlocking(UA_Server *server, UA_AsyncOperationType
UA_Boolean bRV = false;
*type = UA_ASYNCOPERATIONTYPE_INVALID;
- UA_LOCK(am->queueLock);
+ UA_LOCK(&am->queueLock);
UA_AsyncOperation *ao = TAILQ_FIRST(&am->newQueue);
if(ao) {
TAILQ_REMOVE(&am->newQueue, ao, pointers);
@@ -26524,18 +26006,11 @@ UA_Server_getAsyncOperationNonBlocking(UA_Server *server, UA_AsyncOperationType
*timeout = ao->parent->timeout;
bRV = true;
}
- UA_UNLOCK(am->queueLock);
+ UA_UNLOCK(&am->queueLock);
return bRV;
}
-UA_Boolean
-UA_Server_getAsyncOperation(UA_Server *server, UA_AsyncOperationType *type,
- const UA_AsyncOperationRequest **request,
- void **context) {
- return UA_Server_getAsyncOperationNonBlocking(server, type, request, context, NULL);
-}
-
/* Worker submits Method Call Response */
void
UA_Server_setAsyncOperationResult(UA_Server *server,
@@ -26551,7 +26026,7 @@ UA_Server_setAsyncOperationResult(UA_Server *server,
return;
}
- UA_LOCK(am->queueLock);
+ UA_LOCK(&am->queueLock);
/* See if the operation is still in the dispatched queue. Otherwise it has
* been removed due to a timeout.
@@ -26570,7 +26045,7 @@ UA_Server_setAsyncOperationResult(UA_Server *server,
if(!found) {
UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
"UA_Server_SetAsyncMethodResult: The operation has timed out");
- UA_UNLOCK(am->queueLock);
+ UA_UNLOCK(&am->queueLock);
return;
}
@@ -26587,7 +26062,7 @@ UA_Server_setAsyncOperationResult(UA_Server *server,
TAILQ_REMOVE(&am->dispatchedQueue, ao, pointers);
TAILQ_INSERT_TAIL(&am->resultQueue, ao, pointers);
- UA_UNLOCK(am->queueLock);
+ UA_UNLOCK(&am->queueLock);
UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER,
"Set the result from the worker thread");
@@ -26600,10 +26075,9 @@ UA_Server_setAsyncOperationResult(UA_Server *server,
static UA_StatusCode
setMethodNodeAsync(UA_Server *server, UA_Session *session,
UA_Node *node, UA_Boolean *isAsync) {
- UA_MethodNode *method = (UA_MethodNode*)node;
- if(method->nodeClass != UA_NODECLASS_METHOD)
+ if(node->head.nodeClass != UA_NODECLASS_METHOD)
return UA_STATUSCODE_BADNODECLASSINVALID;
- method->async = *isAsync;
+ node->methodNode.async = *isAsync;
return UA_STATUSCODE_GOOD;
}
@@ -26649,7 +26123,7 @@ UA_Server_processServiceOperationsAsync(UA_Server *server, UA_Session *session,
#endif
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/src/pubsub/ua_pubsub_networkmessage.c" ***********************************/
+/**** amalgamated original file "/src/pubsub/ua_pubsub_networkmessage.c" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -26660,8 +26134,8 @@ UA_Server_processServiceOperationsAsync(UA_Server *server, UA_Session *session,
*/
-#ifdef UA_ENABLE_PUBSUB /* conditional compilation */
+#ifdef UA_ENABLE_PUBSUB /* conditional compilation */
const UA_Byte NM_VERSION_MASK = 15;
const UA_Byte NM_PUBLISHER_ID_ENABLED_MASK = 16;
@@ -26705,21 +26179,34 @@ static UA_Boolean UA_DataSetMessageHeader_DataSetFlags2Enabled(const UA_DataSetM
UA_StatusCode
UA_NetworkMessage_updateBufferedMessage(UA_NetworkMessageOffsetBuffer *buffer){
UA_StatusCode rv = UA_STATUSCODE_GOOD;
- for (size_t i = 0; i < buffer->offsetsSize; ++i) {
+ for(size_t i = 0; i < buffer->offsetsSize; ++i) {
+ UA_NetworkMessageOffset *nmo = &buffer->offsets[i];
const UA_Byte *bufEnd = &buffer->buffer.data[buffer->buffer.length];
- UA_Byte *bufPos = &buffer->buffer.data[buffer->offsets[i].offset];
- switch (buffer->offsets[i].contentType) {
+ UA_Byte *bufPos = &buffer->buffer.data[nmo->offset];
+ switch(nmo->contentType) {
case UA_PUBSUB_OFFSETTYPE_DATASETMESSAGE_SEQUENCENUMBER:
- rv = UA_UInt16_encodeBinary((UA_UInt16 *) buffer->offsets[i].offsetData.value.value->value.data, &bufPos, bufEnd);
- break;
case UA_PUBSUB_OFFSETTYPE_NETWORKMESSAGE_SEQUENCENUMBER:
- rv = UA_UInt16_encodeBinary((UA_UInt16 *) buffer->offsets[i].offsetData.value.value->value.data, &bufPos, bufEnd);
+ rv = UA_UInt16_encodeBinary((UA_UInt16 *)nmo->offsetData.value.value->value.data, &bufPos, bufEnd);
+ if(*((UA_UInt16 *)nmo->offsetData.value.value->value.data) < UA_UINT16_MAX){
+ (*((UA_UInt16 *)nmo->offsetData.value.value->value.data))++;
+ } else {
+ (*((UA_UInt16 *)nmo->offsetData.value.value->value.data)) = 0;
+ }
break;
case UA_PUBSUB_OFFSETTYPE_PAYLOAD_DATAVALUE:
- rv = UA_DataValue_encodeBinary(buffer->offsets[i].offsetData.value.value, &bufPos, bufEnd);
+ rv = UA_DataValue_encodeBinary(nmo->offsetData.value.value,
+ &bufPos, bufEnd);
break;
case UA_PUBSUB_OFFSETTYPE_PAYLOAD_VARIANT:
- rv = UA_Variant_encodeBinary(&buffer->offsets[i].offsetData.value.value->value, &bufPos, bufEnd);
+ rv = UA_Variant_encodeBinary(&nmo->offsetData.value.value->value,
+ &bufPos, bufEnd);
+ break;
+ case UA_PUBSUB_OFFSETTYPE_PAYLOAD_RAW:
+ rv = UA_encodeBinaryInternal(nmo->offsetData.value.value->value.data,
+ nmo->offsetData.value.value->value.type,
+ &bufPos, &bufEnd, NULL, NULL);
+ break;
+ case UA_PUBSUB_OFFSETTYPE_NETWORKMESSAGE_FIELDENCDODING:
break;
default:
return UA_STATUSCODE_BADNOTSUPPORTED;
@@ -26729,8 +26216,99 @@ UA_NetworkMessage_updateBufferedMessage(UA_NetworkMessageOffsetBuffer *buffer){
}
UA_StatusCode
-UA_NetworkMessage_encodeBinary(const UA_NetworkMessage* src, UA_Byte **bufPos,
- const UA_Byte *bufEnd) {
+UA_NetworkMessage_updateBufferedNwMessage(UA_NetworkMessageOffsetBuffer *buffer,
+ const UA_ByteString *src, size_t *bufferPosition){
+ UA_StatusCode rv = UA_STATUSCODE_GOOD;
+ size_t payloadCounter = 0;
+ size_t offset = 0;
+ UA_DataSetMessage* dsm = buffer->nm->payload.dataSetPayload.dataSetMessages; //Considering one DSM in RT TODO: Clarify multiple DSM
+ UA_DataSetMessageHeader header;
+ size_t smallestRawOffset = UA_UINT32_MAX;
+
+ for (size_t i = 0; i < buffer->offsetsSize; ++i) {
+ offset = buffer->offsets[i].offset + *bufferPosition;
+ switch (buffer->offsets[i].contentType) {
+ case UA_PUBSUB_OFFSETTYPE_NETWORKMESSAGE_FIELDENCDODING:
+ rv = UA_DataSetMessageHeader_decodeBinary(src, &offset, &header);
+ if(rv != UA_STATUSCODE_GOOD)
+ return rv;
+ break;
+ case UA_PUBSUB_OFFSETTYPE_PUBLISHERID:
+ switch (buffer->nm->publisherIdType) {
+ case UA_PUBLISHERDATATYPE_BYTE:
+ rv = UA_Byte_decodeBinary(src, &offset, &(buffer->nm->publisherId.publisherIdByte));
+ break;
+ case UA_PUBLISHERDATATYPE_UINT16:
+ rv = UA_UInt16_decodeBinary(src, &offset, &(buffer->nm->publisherId.publisherIdUInt16));
+ break;
+ case UA_PUBLISHERDATATYPE_UINT32:
+ rv = UA_UInt32_decodeBinary(src, &offset, &(buffer->nm->publisherId.publisherIdUInt32));
+ break;
+ case UA_PUBLISHERDATATYPE_UINT64:
+ rv = UA_UInt64_decodeBinary(src, &offset, &(buffer->nm->publisherId.publisherIdUInt64));
+ break;
+ default:
+ return UA_STATUSCODE_BADNOTSUPPORTED;
+ }
+ break;
+ case UA_PUBSUB_OFFSETTYPE_WRITERGROUPID:
+ rv = UA_UInt16_decodeBinary(src, &offset, &buffer->nm->groupHeader.writerGroupId);
+ UA_CHECK_STATUS(rv, return rv);
+ break;
+ case UA_PUBSUB_OFFSETTYPE_DATASETWRITERID:
+ rv = UA_UInt16_decodeBinary(src, &offset,
+ &buffer->nm->payloadHeader.dataSetPayloadHeader.dataSetWriterIds[0]); /* TODO */
+ UA_CHECK_STATUS(rv, return rv);
+ break;
+ case UA_PUBSUB_OFFSETTYPE_NETWORKMESSAGE_SEQUENCENUMBER:
+ rv = UA_UInt16_decodeBinary(src, &offset, &buffer->nm->groupHeader.sequenceNumber);
+ UA_CHECK_STATUS(rv, return rv);
+ break;
+ case UA_PUBSUB_OFFSETTYPE_DATASETMESSAGE_SEQUENCENUMBER:
+ rv = UA_UInt16_decodeBinary(src, &offset, &(dsm->header.dataSetMessageSequenceNr));
+ UA_CHECK_STATUS(rv, return rv);
+ break;
+ case UA_PUBSUB_OFFSETTYPE_PAYLOAD_DATAVALUE:
+ rv = UA_DataValue_decodeBinary(src, &offset,
+ &(dsm->data.keyFrameData.dataSetFields[payloadCounter]));
+ UA_CHECK_STATUS(rv, return rv);
+ payloadCounter++;
+ break;
+ case UA_PUBSUB_OFFSETTYPE_PAYLOAD_VARIANT:
+ rv = UA_Variant_decodeBinary(src, &offset,
+ &dsm->data.keyFrameData.dataSetFields[payloadCounter].value);
+ UA_CHECK_STATUS(rv, return rv);
+ dsm->data.keyFrameData.dataSetFields[payloadCounter].hasValue = true;
+ payloadCounter++;
+ break;
+ case UA_PUBSUB_OFFSETTYPE_PAYLOAD_RAW:
+ /* We need only the start address of the raw fields */
+ if (smallestRawOffset > offset){
+ smallestRawOffset = offset;
+ dsm->data.keyFrameData.rawFields.data = &src->data[offset];
+ dsm->data.keyFrameData.rawFields.length = buffer->rawMessageLength;
+ }
+ payloadCounter++;
+ break;
+ default:
+ return UA_STATUSCODE_BADNOTSUPPORTED;
+ }
+ }
+ //check if the frame is of type "raw" payload
+ if(smallestRawOffset != UA_UINT32_MAX){
+ *bufferPosition = smallestRawOffset + buffer->rawMessageLength;
+ } else {
+ *bufferPosition = offset;
+ }
+
+ return rv;
+}
+
+static
+UA_StatusCode
+UA_NetworkMessageHeader_encodeBinary(const UA_NetworkMessage *src, UA_Byte **bufPos,
+ const UA_Byte *bufEnd) {
+
/* UADPVersion + UADP Flags */
UA_Byte v = src->version;
if(src->publisherIdEnabled)
@@ -26746,9 +26324,7 @@ UA_NetworkMessage_encodeBinary(const UA_NetworkMessage* src, UA_Byte **bufPos,
v |= NM_EXTENDEDFLAGS1_ENABLED_MASK;
UA_StatusCode rv = UA_Byte_encodeBinary(&v, bufPos, bufEnd);
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
-
+ UA_CHECK_STATUS(rv, return rv);
// ExtendedFlags1
if(UA_NetworkMessage_ExtendedFlags1Enabled(src)) {
v = (UA_Byte)src->publisherIdType;
@@ -26769,8 +26345,7 @@ UA_NetworkMessage_encodeBinary(const UA_NetworkMessage* src, UA_Byte **bufPos,
v |= NM_EXTENDEDFLAGS2_ENABLED_MASK;
rv = UA_Byte_encodeBinary(&v, bufPos, bufEnd);
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
+ UA_CHECK_STATUS(rv, return rv);
// ExtendedFlags2
if(UA_NetworkMessage_ExtendedFlags2Enabled(src)) {
@@ -26785,8 +26360,7 @@ UA_NetworkMessage_encodeBinary(const UA_NetworkMessage* src, UA_Byte **bufPos,
v |= NM_PROMOTEDFIELDS_ENABLED_MASK;
rv = UA_Byte_encodeBinary(&v, bufPos, bufEnd);
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
+ UA_CHECK_STATUS(rv, return rv);
}
}
@@ -26817,89 +26391,99 @@ UA_NetworkMessage_encodeBinary(const UA_NetworkMessage* src, UA_Byte **bufPos,
rv = UA_STATUSCODE_BADINTERNALERROR;
break;
}
-
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
+ UA_CHECK_STATUS(rv, return rv);
}
// DataSetClassId
if(src->dataSetClassIdEnabled) {
rv = UA_Guid_encodeBinary(&(src->dataSetClassId), bufPos, bufEnd);
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
+ UA_CHECK_STATUS(rv, return rv);
}
+ return UA_STATUSCODE_GOOD;
+}
- // Group Header
- if(src->groupHeaderEnabled) {
- v = 0;
+static
+UA_StatusCode
+UA_GroupHeader_encodeBinary(const UA_NetworkMessage* src, UA_Byte **bufPos,
+ const UA_Byte *bufEnd) {
- if(src->groupHeader.writerGroupIdEnabled)
- v |= GROUP_HEADER_WRITER_GROUPID_ENABLED;
+ UA_Byte v = 0;
- if(src->groupHeader.groupVersionEnabled)
- v |= GROUP_HEADER_GROUP_VERSION_ENABLED;
+ if(src->groupHeader.writerGroupIdEnabled)
+ v |= GROUP_HEADER_WRITER_GROUPID_ENABLED;
- if(src->groupHeader.networkMessageNumberEnabled)
- v |= GROUP_HEADER_NM_NUMBER_ENABLED;
+ if(src->groupHeader.groupVersionEnabled)
+ v |= GROUP_HEADER_GROUP_VERSION_ENABLED;
- if(src->groupHeader.sequenceNumberEnabled)
- v |= GROUP_HEADER_SEQUENCE_NUMBER_ENABLED;
+ if(src->groupHeader.networkMessageNumberEnabled)
+ v |= GROUP_HEADER_NM_NUMBER_ENABLED;
- rv = UA_Byte_encodeBinary(&v, bufPos, bufEnd);
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
+ if(src->groupHeader.sequenceNumberEnabled)
+ v |= GROUP_HEADER_SEQUENCE_NUMBER_ENABLED;
- if(src->groupHeader.writerGroupIdEnabled) {
- rv = UA_UInt16_encodeBinary(&(src->groupHeader.writerGroupId), bufPos, bufEnd);
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
- }
+ UA_StatusCode rv = UA_Byte_encodeBinary(&v, bufPos, bufEnd);
+ UA_CHECK_STATUS(rv, return rv);
- if(src->groupHeader.groupVersionEnabled) {
- rv = UA_UInt32_encodeBinary(&(src->groupHeader.groupVersion), bufPos, bufEnd);
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
- }
+ if(src->groupHeader.writerGroupIdEnabled) {
+ rv = UA_UInt16_encodeBinary(&(src->groupHeader.writerGroupId), bufPos, bufEnd);
+ UA_CHECK_STATUS(rv, return rv);
+ }
- if(src->groupHeader.networkMessageNumberEnabled) {
- rv = UA_UInt16_encodeBinary(&(src->groupHeader.networkMessageNumber), bufPos, bufEnd);
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
- }
+ if(src->groupHeader.groupVersionEnabled) {
+ rv = UA_UInt32_encodeBinary(&(src->groupHeader.groupVersion), bufPos, bufEnd);
+ UA_CHECK_STATUS(rv, return rv);
+ }
- if(src->groupHeader.sequenceNumberEnabled) {
- rv = UA_UInt16_encodeBinary(&(src->groupHeader.sequenceNumber), bufPos, bufEnd);
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
- }
+ if(src->groupHeader.networkMessageNumberEnabled) {
+ rv = UA_UInt16_encodeBinary(&(src->groupHeader.networkMessageNumber), bufPos, bufEnd);
+ UA_CHECK_STATUS(rv, return rv);
}
- // Payload-Header
- if(src->payloadHeaderEnabled) {
- if(src->networkMessageType != UA_NETWORKMESSAGE_DATASET)
- return UA_STATUSCODE_BADNOTIMPLEMENTED;
-
- rv = UA_Byte_encodeBinary(&(src->payloadHeader.dataSetPayloadHeader.count), bufPos, bufEnd);
+ if(src->groupHeader.sequenceNumberEnabled) {
+ rv = UA_UInt16_encodeBinary(&(src->groupHeader.sequenceNumber), bufPos, bufEnd);
+ UA_CHECK_STATUS(rv, return rv);
+ }
+ return UA_STATUSCODE_GOOD;
+}
- if(src->payloadHeader.dataSetPayloadHeader.dataSetWriterIds == NULL)
- return UA_STATUSCODE_BADENCODINGERROR;
-
- for(UA_Byte i = 0; i < src->payloadHeader.dataSetPayloadHeader.count; i++) {
- rv = UA_UInt16_encodeBinary(&(src->payloadHeader.dataSetPayloadHeader.dataSetWriterIds[i]),
- bufPos, bufEnd);
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
- }
+static
+UA_StatusCode
+UA_PayloadHeader_encodeBinary(const UA_NetworkMessage* src, UA_Byte **bufPos,
+ const UA_Byte *bufEnd) {
+
+ if(src->networkMessageType != UA_NETWORKMESSAGE_DATASET)
+ return UA_STATUSCODE_BADNOTIMPLEMENTED;
+
+ UA_StatusCode rv = UA_Byte_encodeBinary(&(src->payloadHeader.dataSetPayloadHeader.count), bufPos, bufEnd);
+ UA_CHECK_STATUS(rv, return rv);
+
+ if(src->payloadHeader.dataSetPayloadHeader.dataSetWriterIds == NULL)
+ return UA_STATUSCODE_BADENCODINGERROR;
+
+ for(UA_Byte i = 0; i < src->payloadHeader.dataSetPayloadHeader.count; i++) {
+ rv = UA_UInt16_encodeBinary(&(src->payloadHeader.dataSetPayloadHeader.dataSetWriterIds[i]),
+ bufPos, bufEnd);
+ UA_CHECK_STATUS(rv, return rv);
}
+ return UA_STATUSCODE_GOOD;
+}
+static
+UA_StatusCode
+UA_ExtendedNetworkMessageHeader_encodeBinary(const UA_NetworkMessage* src, UA_Byte **bufPos,
+ const UA_Byte *bufEnd) {
+
+ UA_StatusCode rv = UA_STATUSCODE_GOOD;
// Timestamp
if(src->timestampEnabled)
rv = UA_DateTime_encodeBinary(&(src->timestamp), bufPos, bufEnd);
+ UA_CHECK_STATUS(rv, return rv);
// Picoseconds
if(src->picosecondsEnabled)
rv = UA_UInt16_encodeBinary(&(src->picoseconds), bufPos, bufEnd);
+ UA_CHECK_STATUS(rv, return rv);
// PromotedFields
if(src->promotedFieldsEnabled) {
/* Size (calculate & encode) */
@@ -26907,56 +26491,95 @@ UA_NetworkMessage_encodeBinary(const UA_NetworkMessage* src, UA_Byte **bufPos,
for(UA_UInt16 i = 0; i < src->promotedFieldsSize; i++)
pfSize = (UA_UInt16) (pfSize + UA_Variant_calcSizeBinary(&src->promotedFields[i]));
rv |= UA_UInt16_encodeBinary(&pfSize, bufPos, bufEnd);
+ UA_CHECK_STATUS(rv, return rv);
for (UA_UInt16 i = 0; i < src->promotedFieldsSize; i++)
rv |= UA_Variant_encodeBinary(&(src->promotedFields[i]), bufPos, bufEnd);
+ UA_CHECK_STATUS(rv, return rv);
}
+ return UA_STATUSCODE_GOOD;
+}
- // SecurityHeader
- if(src->securityEnabled) {
- // SecurityFlags
- v = 0;
- if(src->securityHeader.networkMessageSigned)
- v |= SECURITY_HEADER_NM_SIGNED;
+static
+UA_StatusCode
+UA_SecurityHeader_encodeBinary(const UA_NetworkMessage* src, UA_Byte **bufPos,
+ const UA_Byte *bufEnd) {
+ // SecurityFlags
+ UA_Byte v = 0;
+ if(src->securityHeader.networkMessageSigned)
+ v |= SECURITY_HEADER_NM_SIGNED;
- if(src->securityHeader.networkMessageEncrypted)
- v |= SECURITY_HEADER_NM_ENCRYPTED;
+ if(src->securityHeader.networkMessageEncrypted)
+ v |= SECURITY_HEADER_NM_ENCRYPTED;
- if(src->securityHeader.securityFooterEnabled)
- v |= SECURITY_HEADER_SEC_FOOTER_ENABLED;
+ if(src->securityHeader.securityFooterEnabled)
+ v |= SECURITY_HEADER_SEC_FOOTER_ENABLED;
- if(src->securityHeader.forceKeyReset)
- v |= SECURITY_HEADER_FORCE_KEY_RESET;
+ if(src->securityHeader.forceKeyReset)
+ v |= SECURITY_HEADER_FORCE_KEY_RESET;
- rv = UA_Byte_encodeBinary(&v, bufPos, bufEnd);
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
+ UA_StatusCode rv = UA_Byte_encodeBinary(&v, bufPos, bufEnd);
+ UA_CHECK_STATUS(rv, return rv);
+ // SecurityTokenId
+ rv = UA_UInt32_encodeBinary(&src->securityHeader.securityTokenId, bufPos, bufEnd);
+ UA_CHECK_STATUS(rv, return rv);
+ // NonceLength
+ UA_Byte nonceLength = (UA_Byte)src->securityHeader.messageNonce.length;
+ rv = UA_Byte_encodeBinary(&nonceLength, bufPos, bufEnd);
+ UA_CHECK_STATUS(rv, return rv);
+ // MessageNonce
+ for (size_t i = 0; i < src->securityHeader.messageNonce.length; i++) {
+ rv = UA_Byte_encodeBinary(&src->securityHeader.messageNonce.data[i],
+ bufPos, bufEnd);
+ UA_CHECK_STATUS(rv, return rv);
+ }
+
+ // SecurityFooterSize
+ if(src->securityHeader.securityFooterEnabled) {
+ rv = UA_UInt16_encodeBinary(&src->securityHeader.securityFooterSize,
+ bufPos, bufEnd);
+ UA_CHECK_STATUS(rv, return rv);
+ }
- // SecurityTokenId
- rv = UA_UInt32_encodeBinary(&src->securityHeader.securityTokenId, bufPos, bufEnd);
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
+ return UA_STATUSCODE_GOOD;
+}
- // NonceLength
- rv = UA_Byte_encodeBinary(&src->securityHeader.nonceLength, bufPos, bufEnd);
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
+UA_StatusCode
+UA_NetworkMessage_encodeHeaders(const UA_NetworkMessage* src, UA_Byte **bufPos,
+ const UA_Byte *bufEnd) {
- // MessageNonce
- for (UA_Byte i = 0; i < src->securityHeader.nonceLength; i++) {
- rv = UA_Byte_encodeBinary(&(src->securityHeader.messageNonce.data[i]), bufPos, bufEnd);
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
- }
+ UA_StatusCode rv = UA_NetworkMessageHeader_encodeBinary(src, bufPos, bufEnd);
+ UA_CHECK_STATUS(rv, return rv);
+ // Group Header
+ if(src->groupHeaderEnabled) {
+ rv = UA_GroupHeader_encodeBinary(src, bufPos, bufEnd);
+ UA_CHECK_STATUS(rv, return rv);
+ }
- // SecurityFooterSize
- if(src->securityHeader.securityFooterEnabled) {
- rv = UA_UInt16_encodeBinary(&src->securityHeader.securityFooterSize, bufPos, bufEnd);
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
- }
+ // Payload Header
+ if(src->payloadHeaderEnabled) {
+ rv = UA_PayloadHeader_encodeBinary(src, bufPos, bufEnd);
+ UA_CHECK_STATUS(rv, return rv);
}
+ // Extended Network Message Header
+ rv = UA_ExtendedNetworkMessageHeader_encodeBinary(src, bufPos, bufEnd);
+ UA_CHECK_STATUS(rv, return rv);
+ // SecurityHeader
+ if(src->securityEnabled) {
+ rv = UA_SecurityHeader_encodeBinary(src, bufPos, bufEnd);
+ UA_CHECK_STATUS(rv, return rv);
+ }
+ return UA_STATUSCODE_GOOD;
+}
+
+
+UA_StatusCode
+UA_NetworkMessage_encodePayload(const UA_NetworkMessage* src, UA_Byte **bufPos,
+ const UA_Byte *bufEnd) {
+
+ UA_StatusCode rv;
+
// Payload
if(src->networkMessageType != UA_NETWORKMESSAGE_DATASET)
return UA_STATUSCODE_BADNOTIMPLEMENTED;
@@ -26978,303 +26601,351 @@ UA_NetworkMessage_encodeBinary(const UA_NetworkMessage* src, UA_Byte **bufPos,
}
rv = UA_UInt16_encodeBinary(&sz, bufPos, bufEnd);
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
+ UA_CHECK_STATUS(rv, return rv);
}
}
}
for(UA_Byte i = 0; i < count; i++) {
rv = UA_DataSetMessage_encodeBinary(&(src->payload.dataSetPayload.dataSetMessages[i]), bufPos, bufEnd);
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
+ UA_CHECK_STATUS(rv, return rv);
}
+ return UA_STATUSCODE_GOOD;
+}
+
+UA_StatusCode
+UA_NetworkMessage_encodeFooters(const UA_NetworkMessage* src, UA_Byte **bufPos,
+ const UA_Byte *bufEnd) {
+
if(src->securityEnabled) {
// SecurityFooter
if(src->securityHeader.securityFooterEnabled) {
- for(UA_Byte i = 0; i < src->securityHeader.securityFooterSize; i++) {
- rv = UA_Byte_encodeBinary(&(src->securityFooter.data[i]), bufPos, bufEnd);
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
+ for(size_t i = 0; i < src->securityHeader.securityFooterSize; i++) {
+ UA_StatusCode rv = UA_Byte_encodeBinary(&(src->securityFooter.data[i]), bufPos, bufEnd);
+ UA_CHECK_STATUS(rv, return rv);
}
}
+ }
+ return UA_STATUSCODE_GOOD;
+}
- // Signature
- if(src->securityHeader.networkMessageSigned) {
- rv = UA_ByteString_encodeBinary(&(src->signature), bufPos, bufEnd);
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
- }
+UA_StatusCode
+UA_NetworkMessage_encodeBinary(const UA_NetworkMessage* src, UA_Byte **bufPos,
+ const UA_Byte *bufEnd, UA_Byte **dataToEncryptStart) {
+
+ UA_StatusCode rv = UA_NetworkMessage_encodeHeaders(src, bufPos, bufEnd);
+ UA_CHECK_STATUS(rv, return rv);
+
+ if(dataToEncryptStart) {
+ *dataToEncryptStart = *bufPos;
}
+ rv = UA_NetworkMessage_encodePayload(src, bufPos, bufEnd);
+ UA_CHECK_STATUS(rv, return rv);
+
+ rv = UA_NetworkMessage_encodeFooters(src, bufPos, bufEnd);
+ UA_CHECK_STATUS(rv, return rv);
+
return UA_STATUSCODE_GOOD;
}
-static UA_StatusCode
-UA_NetworkMessage_decodeBinaryInternal(const UA_ByteString *src, size_t *offset,
- UA_NetworkMessage* dst) {
- memset(dst, 0, sizeof(UA_NetworkMessage));
- UA_Byte v = 0;
- UA_StatusCode rv = UA_Byte_decodeBinary(src, offset, &v);
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
+UA_StatusCode
+UA_NetworkMessageHeader_decodeBinary(const UA_ByteString *src, size_t *offset, UA_NetworkMessage *dst) {
+ UA_Byte decoded = 0;
+ UA_StatusCode rv = UA_Byte_decodeBinary(src, offset, &decoded);
+ UA_CHECK_STATUS(rv, return rv);
- dst->version = v & NM_VERSION_MASK;
-
- if((v & NM_PUBLISHER_ID_ENABLED_MASK) != 0)
+ dst->version = decoded & NM_VERSION_MASK;
+
+ if((decoded & NM_PUBLISHER_ID_ENABLED_MASK) != 0)
dst->publisherIdEnabled = true;
- if((v & NM_GROUP_HEADER_ENABLED_MASK) != 0)
+ if((decoded & NM_GROUP_HEADER_ENABLED_MASK) != 0)
dst->groupHeaderEnabled = true;
- if((v & NM_PAYLOAD_HEADER_ENABLED_MASK) != 0)
+ if((decoded & NM_PAYLOAD_HEADER_ENABLED_MASK) != 0)
dst->payloadHeaderEnabled = true;
-
- if((v & NM_EXTENDEDFLAGS1_ENABLED_MASK) != 0) {
- v = 0;
- rv = UA_Byte_decodeBinary(src, offset, &v);
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
- dst->publisherIdType = (UA_PublisherIdDatatype)(v & NM_PUBLISHER_ID_MASK);
- if((v & NM_DATASET_CLASSID_ENABLED_MASK) != 0)
+ if((decoded & NM_EXTENDEDFLAGS1_ENABLED_MASK) != 0) {
+ decoded = 0;
+ rv = UA_Byte_decodeBinary(src, offset, &decoded);
+ UA_CHECK_STATUS(rv, return rv);
+
+ dst->publisherIdType = (UA_PublisherIdDatatype)(decoded & NM_PUBLISHER_ID_MASK);
+ if((decoded & NM_DATASET_CLASSID_ENABLED_MASK) != 0)
dst->dataSetClassIdEnabled = true;
- if((v & NM_SECURITY_ENABLED_MASK) != 0)
+ if((decoded & NM_SECURITY_ENABLED_MASK) != 0)
dst->securityEnabled = true;
- if((v & NM_TIMESTAMP_ENABLED_MASK) != 0)
+ if((decoded & NM_TIMESTAMP_ENABLED_MASK) != 0)
dst->timestampEnabled = true;
- if((v & NM_PICOSECONDS_ENABLED_MASK) != 0)
+ if((decoded & NM_PICOSECONDS_ENABLED_MASK) != 0)
dst->picosecondsEnabled = true;
- if((v & NM_EXTENDEDFLAGS2_ENABLED_MASK) != 0) {
- v = 0;
- rv = UA_Byte_decodeBinary(src, offset, &v);
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
+ if((decoded & NM_EXTENDEDFLAGS2_ENABLED_MASK) != 0) {
+ decoded = 0;
+ rv = UA_Byte_decodeBinary(src, offset, &decoded);
+ UA_CHECK_STATUS(rv, return rv);
- if((v & NM_CHUNK_MESSAGE_MASK) != 0)
+ if((decoded & NM_CHUNK_MESSAGE_MASK) != 0)
dst->chunkMessage = true;
- if((v & NM_PROMOTEDFIELDS_ENABLED_MASK) != 0)
+ if((decoded & NM_PROMOTEDFIELDS_ENABLED_MASK) != 0)
dst->promotedFieldsEnabled = true;
- v = v & NM_NETWORK_MSG_TYPE_MASK;
- v = (UA_Byte) (v >> NM_SHIFT_LEN);
- dst->networkMessageType = (UA_NetworkMessageType)v;
+ decoded = decoded & NM_NETWORK_MSG_TYPE_MASK;
+ decoded = (UA_Byte) (decoded >> NM_SHIFT_LEN);
+ dst->networkMessageType = (UA_NetworkMessageType)decoded;
}
}
if(dst->publisherIdEnabled) {
switch (dst->publisherIdType) {
- case UA_PUBLISHERDATATYPE_BYTE:
- rv = UA_Byte_decodeBinary(src, offset, &(dst->publisherId.publisherIdByte));
- break;
+ case UA_PUBLISHERDATATYPE_BYTE:
+ rv = UA_Byte_decodeBinary(src, offset, &(dst->publisherId.publisherIdByte));
+ break;
- case UA_PUBLISHERDATATYPE_UINT16:
- rv = UA_UInt16_decodeBinary(src, offset, &(dst->publisherId.publisherIdUInt16));
- break;
+ case UA_PUBLISHERDATATYPE_UINT16:
+ rv = UA_UInt16_decodeBinary(src, offset, &(dst->publisherId.publisherIdUInt16));
+ break;
- case UA_PUBLISHERDATATYPE_UINT32:
- rv = UA_UInt32_decodeBinary(src, offset, &(dst->publisherId.publisherIdUInt32));
- break;
+ case UA_PUBLISHERDATATYPE_UINT32:
+ rv = UA_UInt32_decodeBinary(src, offset, &(dst->publisherId.publisherIdUInt32));
+ break;
- case UA_PUBLISHERDATATYPE_UINT64:
- rv = UA_UInt64_decodeBinary(src, offset, &(dst->publisherId.publisherIdUInt64));
- break;
+ case UA_PUBLISHERDATATYPE_UINT64:
+ rv = UA_UInt64_decodeBinary(src, offset, &(dst->publisherId.publisherIdUInt64));
+ break;
- case UA_PUBLISHERDATATYPE_STRING:
- rv = UA_String_decodeBinary(src, offset, &(dst->publisherId.publisherIdString));
- break;
+ case UA_PUBLISHERDATATYPE_STRING:
+ rv = UA_String_decodeBinary(src, offset, &(dst->publisherId.publisherIdString));
+ break;
- default:
- rv = UA_STATUSCODE_BADINTERNALERROR;
- break;
+ default:
+ rv = UA_STATUSCODE_BADINTERNALERROR;
+ break;
}
-
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
+ UA_CHECK_STATUS(rv, return rv);
}
if(dst->dataSetClassIdEnabled) {
rv = UA_Guid_decodeBinary(src, offset, &(dst->dataSetClassId));
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
+ UA_CHECK_STATUS(rv, return rv);
}
+ return UA_STATUSCODE_GOOD;
+}
- // GroupHeader
- if(dst->groupHeaderEnabled) {
- v = 0;
- rv = UA_Byte_decodeBinary(src, offset, &v);
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
-
- if((v & GROUP_HEADER_WRITER_GROUPID_ENABLED) != 0)
- dst->groupHeader.writerGroupIdEnabled = true;
+static UA_StatusCode
+UA_GroupHeader_decodeBinary(const UA_ByteString *src, size_t *offset,
+ UA_NetworkMessage* dst) {
+ UA_Byte decoded = 0;
+ UA_StatusCode rv = UA_Byte_decodeBinary(src, offset, &decoded);
+ UA_CHECK_STATUS(rv, return rv);
- if((v & GROUP_HEADER_GROUP_VERSION_ENABLED) != 0)
- dst->groupHeader.groupVersionEnabled = true;
+ if((decoded & GROUP_HEADER_WRITER_GROUPID_ENABLED) != 0)
+ dst->groupHeader.writerGroupIdEnabled = true;
- if((v & GROUP_HEADER_NM_NUMBER_ENABLED) != 0)
- dst->groupHeader.networkMessageNumberEnabled = true;
+ if((decoded & GROUP_HEADER_GROUP_VERSION_ENABLED) != 0)
+ dst->groupHeader.groupVersionEnabled = true;
- if((v & GROUP_HEADER_SEQUENCE_NUMBER_ENABLED) != 0)
- dst->groupHeader.sequenceNumberEnabled = true;
+ if((decoded & GROUP_HEADER_NM_NUMBER_ENABLED) != 0)
+ dst->groupHeader.networkMessageNumberEnabled = true;
- if(dst->groupHeader.writerGroupIdEnabled) {
- rv = UA_UInt16_decodeBinary(src, offset, &dst->groupHeader.writerGroupId);
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
- }
+ if((decoded & GROUP_HEADER_SEQUENCE_NUMBER_ENABLED) != 0)
+ dst->groupHeader.sequenceNumberEnabled = true;
- if(dst->groupHeader.groupVersionEnabled) {
- rv = UA_UInt32_decodeBinary(src, offset, &dst->groupHeader.groupVersion);
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
- }
-
- if(dst->groupHeader.networkMessageNumberEnabled) {
- rv = UA_UInt16_decodeBinary(src, offset, &dst->groupHeader.networkMessageNumber);
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
- }
-
- if(dst->groupHeader.sequenceNumberEnabled) {
- rv = UA_UInt16_decodeBinary(src, offset, &dst->groupHeader.sequenceNumber);
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
- }
+ if(dst->groupHeader.writerGroupIdEnabled) {
+ rv = UA_UInt16_decodeBinary(src, offset, &dst->groupHeader.writerGroupId);
+ UA_CHECK_STATUS(rv, return rv);
+ }
+ if(dst->groupHeader.groupVersionEnabled) {
+ rv = UA_UInt32_decodeBinary(src, offset, &dst->groupHeader.groupVersion);
+ UA_CHECK_STATUS(rv, return rv);
+ }
+ if(dst->groupHeader.networkMessageNumberEnabled) {
+ rv = UA_UInt16_decodeBinary(src, offset, &dst->groupHeader.networkMessageNumber);
+ UA_CHECK_STATUS(rv, return rv);
+ }
+ if(dst->groupHeader.sequenceNumberEnabled) {
+ rv = UA_UInt16_decodeBinary(src, offset, &dst->groupHeader.sequenceNumber);
+ UA_CHECK_STATUS(rv, return rv);
}
+ return UA_STATUSCODE_GOOD;
+}
- // Payload-Header
- if(dst->payloadHeaderEnabled) {
- if(dst->networkMessageType != UA_NETWORKMESSAGE_DATASET)
- return UA_STATUSCODE_BADNOTIMPLEMENTED;
+static UA_StatusCode
+UA_PayloadHeader_decodeBinary(const UA_ByteString *src, size_t *offset,
+ UA_NetworkMessage* dst) {
- rv = UA_Byte_decodeBinary(src, offset, &dst->payloadHeader.dataSetPayloadHeader.count);
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
+ if(dst->networkMessageType != UA_NETWORKMESSAGE_DATASET)
+ return UA_STATUSCODE_BADNOTIMPLEMENTED;
- dst->payloadHeader.dataSetPayloadHeader.dataSetWriterIds =
- (UA_UInt16 *)UA_Array_new(dst->payloadHeader.dataSetPayloadHeader.count,
- &UA_TYPES[UA_TYPES_UINT16]);
- for (UA_Byte i = 0; i < dst->payloadHeader.dataSetPayloadHeader.count; i++) {
- rv = UA_UInt16_decodeBinary(src, offset,
- &dst->payloadHeader.dataSetPayloadHeader.dataSetWriterIds[i]);
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
- }
+ UA_StatusCode rv = UA_Byte_decodeBinary(src, offset, &dst->payloadHeader.dataSetPayloadHeader.count);
+ UA_CHECK_STATUS(rv, return rv);
+
+ dst->payloadHeader.dataSetPayloadHeader.dataSetWriterIds =
+ (UA_UInt16 *)UA_Array_new(dst->payloadHeader.dataSetPayloadHeader.count,
+ &UA_TYPES[UA_TYPES_UINT16]);
+ for (UA_Byte i = 0; i < dst->payloadHeader.dataSetPayloadHeader.count; i++) {
+ rv = UA_UInt16_decodeBinary(src, offset,
+ &dst->payloadHeader.dataSetPayloadHeader.dataSetWriterIds[i]);
+ UA_CHECK_STATUS(rv, return rv);
}
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_StatusCode
+UA_ExtendedNetworkMessageHeader_decodeBinary(const UA_ByteString *src, size_t *offset,
+ UA_NetworkMessage* dst) {
+ UA_StatusCode rv;
// Timestamp
if(dst->timestampEnabled) {
rv = UA_DateTime_decodeBinary(src, offset, &(dst->timestamp));
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
+ UA_CHECK_STATUS(rv, goto error);
}
// Picoseconds
if(dst->picosecondsEnabled) {
rv = UA_UInt16_decodeBinary(src, offset, &(dst->picoseconds));
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
+ UA_CHECK_STATUS(rv, goto error);
}
- // PromotedFields
+ // PromotedFields
if(dst->promotedFieldsEnabled) {
// Size
UA_UInt16 promotedFieldsSize = 0;
rv = UA_UInt16_decodeBinary(src, offset, &promotedFieldsSize);
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
+ UA_CHECK_STATUS(rv, goto error);
// promotedFieldsSize: here size in Byte, not the number of objects!
if(promotedFieldsSize > 0) {
- // store offset, later compared with promotedFieldsSize
+ // store offset, later compared with promotedFieldsSize
size_t offsetEnd = (*offset) + promotedFieldsSize;
unsigned int counter = 0;
do {
if(counter == 0) {
dst->promotedFields = (UA_Variant*)UA_malloc(UA_TYPES[UA_TYPES_VARIANT].memSize);
+ UA_CHECK_MEM(dst->promotedFields,
+ return UA_STATUSCODE_BADOUTOFMEMORY);
// set promotedFieldsSize to the number of objects
dst->promotedFieldsSize = (UA_UInt16) (counter + 1);
} else {
dst->promotedFields = (UA_Variant*)
UA_realloc(dst->promotedFields,
- UA_TYPES[UA_TYPES_VARIANT].memSize * (counter + 1));
+ (size_t) UA_TYPES[UA_TYPES_VARIANT].memSize * (counter + 1));
+ UA_CHECK_MEM(dst->promotedFields,
+ return UA_STATUSCODE_BADOUTOFMEMORY);
// set promotedFieldsSize to the number of objects
dst->promotedFieldsSize = (UA_UInt16) (counter + 1);
}
UA_Variant_init(&dst->promotedFields[counter]);
rv = UA_Variant_decodeBinary(src, offset, &dst->promotedFields[counter]);
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
+ UA_CHECK_STATUS(rv, goto error);
+
counter++;
} while ((*offset) < offsetEnd);
}
}
+ return UA_STATUSCODE_GOOD;
- // SecurityHeader
- if(dst->securityEnabled) {
- // SecurityFlags
- v = 0;
- rv = UA_Byte_decodeBinary(src, offset, &v);
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
+error:
+ if (dst->promotedFields) {
+ UA_free(dst->promotedFields);
+ }
+ return rv;
+}
- if((v & SECURITY_HEADER_NM_SIGNED) != 0)
- dst->securityHeader.networkMessageSigned = true;
+static UA_StatusCode
+UA_SecurityHeader_decodeBinary(const UA_ByteString *src, size_t *offset,
+ UA_NetworkMessage* dst) {
+ UA_Byte decoded = 0;
+ // SecurityFlags
+ decoded = 0;
+ UA_StatusCode rv = UA_Byte_decodeBinary(src, offset, &decoded);
+ UA_CHECK_STATUS(rv, return rv);
- if((v & SECURITY_HEADER_NM_ENCRYPTED) != 0)
- dst->securityHeader.networkMessageEncrypted = true;
+ if((decoded & SECURITY_HEADER_NM_SIGNED) != 0)
+ dst->securityHeader.networkMessageSigned = true;
- if((v & SECURITY_HEADER_SEC_FOOTER_ENABLED) != 0)
- dst->securityHeader.securityFooterEnabled = true;
+ if((decoded & SECURITY_HEADER_NM_ENCRYPTED) != 0)
+ dst->securityHeader.networkMessageEncrypted = true;
- if((v & SECURITY_HEADER_FORCE_KEY_RESET) != 0)
- dst->securityHeader.forceKeyReset = true;
+ if((decoded & SECURITY_HEADER_SEC_FOOTER_ENABLED) != 0)
+ dst->securityHeader.securityFooterEnabled = true;
- // SecurityTokenId
- rv = UA_UInt32_decodeBinary(src, offset, &dst->securityHeader.securityTokenId);
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
+ if((decoded & SECURITY_HEADER_FORCE_KEY_RESET) != 0)
+ dst->securityHeader.forceKeyReset = true;
- // NonceLength
- rv = UA_Byte_decodeBinary(src, offset, &dst->securityHeader.nonceLength);
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
+ // SecurityTokenId
+ rv = UA_UInt32_decodeBinary(src, offset, &dst->securityHeader.securityTokenId);
+ UA_CHECK_STATUS(rv, return rv);
- // MessageNonce
- if(dst->securityHeader.nonceLength > 0) {
- rv = UA_ByteString_allocBuffer(&dst->securityHeader.messageNonce,
- dst->securityHeader.nonceLength);
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
+ // NonceLength
+ UA_Byte nonceLength;
+ rv = UA_Byte_decodeBinary(src, offset, &nonceLength);
+ UA_CHECK_STATUS(rv, return rv);
- for (UA_Byte i = 0; i < dst->securityHeader.nonceLength; i++) {
- rv = UA_Byte_decodeBinary(src, offset, &(dst->securityHeader.messageNonce.data[i]));
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
- }
+ // MessageNonce
+ if(nonceLength > 0) {
+ //TODO: check for memory leaks
+ rv = UA_ByteString_allocBuffer(&dst->securityHeader.messageNonce, nonceLength);
+ UA_CHECK_STATUS(rv, return rv);
+ for (UA_Byte i = 0; i < nonceLength; i++) {
+ rv = UA_Byte_decodeBinary(src, offset,
+ &dst->securityHeader.messageNonce.data[i]);
+ UA_CHECK_STATUS(rv, return rv);
}
+ }
+ // SecurityFooterSize
+ if(dst->securityHeader.securityFooterEnabled) {
+ rv = UA_UInt16_decodeBinary(src, offset, &dst->securityHeader.securityFooterSize);
+ UA_CHECK_STATUS(rv, return rv);
+ }
+ return UA_STATUSCODE_GOOD;
+}
- // SecurityFooterSize
- if(dst->securityHeader.securityFooterEnabled) {
- rv = UA_UInt16_decodeBinary(src, offset, &dst->securityHeader.securityFooterSize);
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
- }
+UA_StatusCode
+UA_NetworkMessage_decodeHeaders(const UA_ByteString *src, size_t *offset, UA_NetworkMessage *dst) {
+
+ UA_StatusCode rv = UA_NetworkMessageHeader_decodeBinary(src, offset, dst);
+ UA_CHECK_STATUS(rv, return rv);
+
+ if (dst->groupHeaderEnabled) {
+ rv = UA_GroupHeader_decodeBinary(src, offset, dst);
+ UA_CHECK_STATUS(rv, return rv);
+ }
+
+ if (dst->payloadHeaderEnabled) {
+ rv = UA_PayloadHeader_decodeBinary(src, offset, dst);
+ UA_CHECK_STATUS(rv, return rv);
+ }
+
+ if (dst->securityEnabled) {
+ rv = UA_SecurityHeader_decodeBinary(src, offset, dst);
+ UA_CHECK_STATUS(rv, return rv);
}
+ rv = UA_ExtendedNetworkMessageHeader_decodeBinary(src, offset, dst);
+ UA_CHECK_STATUS(rv, return rv);
+
+ return UA_STATUSCODE_GOOD;
+}
+
+UA_StatusCode
+UA_NetworkMessage_decodePayload(const UA_ByteString *src, size_t *offset, UA_NetworkMessage *dst) {
+
// Payload
if(dst->networkMessageType != UA_NETWORKMESSAGE_DATASET)
return UA_STATUSCODE_BADNOTIMPLEMENTED;
+ UA_StatusCode rv;
+
UA_Byte count = 1;
if(dst->payloadHeaderEnabled) {
count = dst->payloadHeader.dataSetPayloadHeader.count;
@@ -27282,64 +26953,100 @@ UA_NetworkMessage_decodeBinaryInternal(const UA_ByteString *src, size_t *offset,
dst->payload.dataSetPayload.sizes = (UA_UInt16 *)UA_Array_new(count, &UA_TYPES[UA_TYPES_UINT16]);
for (UA_Byte i = 0; i < count; i++) {
rv = UA_UInt16_decodeBinary(src, offset, &(dst->payload.dataSetPayload.sizes[i]));
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
+ UA_CHECK_STATUS(rv, return rv);
}
}
}
dst->payload.dataSetPayload.dataSetMessages = (UA_DataSetMessage*)
UA_calloc(count, sizeof(UA_DataSetMessage));
- for(UA_Byte i = 0; i < count; i++) {
- rv = UA_DataSetMessage_decodeBinary(src, offset, &(dst->payload.dataSetPayload.dataSetMessages[i]));
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
+ UA_CHECK_MEM(dst->payload.dataSetPayload.dataSetMessages,
+ return UA_STATUSCODE_BADOUTOFMEMORY);
+
+ if(count == 1)
+ rv = UA_DataSetMessage_decodeBinary(src, offset,
+ &(dst->payload.dataSetPayload.dataSetMessages[0]),
+ 0);
+ else {
+ for(UA_Byte i = 0; i < count; i++) {
+ rv = UA_DataSetMessage_decodeBinary(src, offset,
+ &(dst->payload.dataSetPayload.dataSetMessages[i]),
+ dst->payload.dataSetPayload.sizes[i]);
+ }
}
+ UA_CHECK_STATUS(rv, return rv);
+
+ return UA_STATUSCODE_GOOD;
+
+ /**
+ * TODO: check if making the cleanup to free its own allocated memory is better,
+ * currently the free happens in a parent context
+ */
+ // error:
+ // if (dst->payload.dataSetPayload.dataSetMessages) {
+ // UA_free(dst->payload.dataSetPayload.dataSetMessages);
+ // }
+ // return rv;
+}
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
+UA_StatusCode
+UA_NetworkMessage_decodeFooters(const UA_ByteString *src, size_t *offset, UA_NetworkMessage *dst) {
- if(dst->securityEnabled) {
+ if (dst->securityEnabled) {
// SecurityFooter
- if(dst->securityHeader.securityFooterEnabled && (dst->securityHeader.securityFooterSize > 0)) {
- rv = UA_ByteString_allocBuffer(&dst->securityFooter, dst->securityHeader.securityFooterSize);
- if (rv != UA_STATUSCODE_GOOD)
- return rv;
+ if(dst->securityHeader.securityFooterEnabled &&
+ (dst->securityHeader.securityFooterSize > 0)) {
+ UA_StatusCode rv = UA_ByteString_allocBuffer(&dst->securityFooter,
+ dst->securityHeader.securityFooterSize);
+ UA_CHECK_STATUS(rv, return rv);
- for (UA_Byte i = 0; i < dst->securityHeader.securityFooterSize; i++) {
+ for(UA_UInt16 i = 0; i < dst->securityHeader.securityFooterSize; i++) {
rv = UA_Byte_decodeBinary(src, offset, &(dst->securityFooter.data[i]));
- if (rv != UA_STATUSCODE_GOOD)
- return rv;
+ UA_CHECK_STATUS(rv, return rv);
}
}
-
- // Signature
- if(dst->securityHeader.networkMessageSigned) {
- rv = UA_ByteString_decodeBinary(src, offset, &(dst->signature));
- if (rv != UA_STATUSCODE_GOOD)
- return rv;
- }
}
-
return UA_STATUSCODE_GOOD;
}
UA_StatusCode
-UA_NetworkMessage_decodeBinary(const UA_ByteString *src, size_t *offset, UA_NetworkMessage* dst) {
- UA_StatusCode retval = UA_NetworkMessage_decodeBinaryInternal(src, offset, dst);
+UA_NetworkMessage_decodeBinary(const UA_ByteString *src, size_t *offset,
+ UA_NetworkMessage* dst) {
- if(retval != UA_STATUSCODE_GOOD)
- UA_NetworkMessage_deleteMembers(dst);
+ UA_StatusCode rv = UA_STATUSCODE_GOOD;
- return retval;
+ /* headers only need to be decoded when not in encryption mode
+ * because headers are already decoded when encryption mode is enabled
+ * to check for security parameters and decrypt/verify
+ *
+ * TODO: check if there is a workaround to use this function
+ * also when encryption is enabled
+ */
+ // #ifndef UA_ENABLE_PUBSUB_ENCRYPTION
+ // if (*offset == 0) {
+ // rv = UA_NetworkMessage_decodeHeaders(src, offset, dst);
+ // UA_CHECK_STATUS(rv, return rv);
+ // }
+ // #endif
+
+ rv = UA_NetworkMessage_decodeHeaders(src, offset, dst);
+ UA_CHECK_STATUS(rv, return rv);
+
+ rv = UA_NetworkMessage_decodePayload(src, offset, dst);
+ UA_CHECK_STATUS(rv, return rv);
+
+ rv = UA_NetworkMessage_decodeFooters(src, offset, dst);
+ UA_CHECK_STATUS(rv, return rv);
+
+ return UA_STATUSCODE_GOOD;
}
static UA_Boolean
increaseOffsetArray(UA_NetworkMessageOffsetBuffer *offsetBuffer) {
UA_NetworkMessageOffset *tmpOffsets = (UA_NetworkMessageOffset *)
UA_realloc(offsetBuffer->offsets, sizeof(UA_NetworkMessageOffset) * (offsetBuffer->offsetsSize + (size_t)1));
- if(!tmpOffsets)
- return false;
+ UA_CHECK_MEM(tmpOffsets, return false);
+
offsetBuffer->offsets = tmpOffsets;
offsetBuffer->offsetsSize++;
return true;
@@ -27348,7 +27055,7 @@ increaseOffsetArray(UA_NetworkMessageOffsetBuffer *offsetBuffer) {
size_t
UA_NetworkMessage_calcSizeBinary(UA_NetworkMessage *p, UA_NetworkMessageOffsetBuffer *offsetBuffer) {
size_t retval = 0;
- UA_Byte byte;
+ UA_Byte byte = 0;
size_t size = UA_Byte_calcSizeBinary(&byte); // UADPVersion + UADPFlags
if(UA_NetworkMessage_ExtendedFlags1Enabled(p)) {
size += UA_Byte_calcSizeBinary(&byte);
@@ -27357,6 +27064,14 @@ UA_NetworkMessage_calcSizeBinary(UA_NetworkMessage *p, UA_NetworkMessageOffsetBu
}
if(p->publisherIdEnabled) {
+ if(offsetBuffer && offsetBuffer->RTsubscriberEnabled){
+ size_t pos = offsetBuffer->offsetsSize;
+ if(!increaseOffsetArray(offsetBuffer))
+ return 0;
+
+ offsetBuffer->offsets[pos].offset = size;
+ offsetBuffer->offsets[pos].contentType = UA_PUBSUB_OFFSETTYPE_PUBLISHERID;
+ }
switch (p->publisherIdType) {
case UA_PUBLISHERDATATYPE_BYTE:
size += UA_Byte_calcSizeBinary(&p->publisherId.publisherIdByte);
@@ -27387,8 +27102,17 @@ UA_NetworkMessage_calcSizeBinary(UA_NetworkMessage *p, UA_NetworkMessageOffsetBu
if(p->groupHeaderEnabled) {
size += UA_Byte_calcSizeBinary(&byte);
- if(p->groupHeader.writerGroupIdEnabled)
+ if(p->groupHeader.writerGroupIdEnabled) {
+ if(offsetBuffer && offsetBuffer->RTsubscriberEnabled){
+ size_t pos = offsetBuffer->offsetsSize;
+ if(!increaseOffsetArray(offsetBuffer))
+ return 0;
+
+ offsetBuffer->offsets[pos].offset = size;
+ offsetBuffer->offsets[pos].contentType = UA_PUBSUB_OFFSETTYPE_WRITERGROUPID;
+ }
size += UA_UInt16_calcSizeBinary(&p->groupHeader.writerGroupId);
+ }
if(p->groupHeader.groupVersionEnabled)
size += UA_UInt32_calcSizeBinary(&p->groupHeader.groupVersion);
@@ -27405,7 +27129,7 @@ UA_NetworkMessage_calcSizeBinary(UA_NetworkMessage *p, UA_NetworkMessageOffsetBu
offsetBuffer->offsets[pos].offset = size;
offsetBuffer->offsets[pos].offsetData.value.value = UA_DataValue_new();
UA_DataValue_init(offsetBuffer->offsets[pos].offsetData.value.value);
- UA_Variant_setScalar(&offsetBuffer->offsets[pos].offsetData.value.value->value,
+ UA_Variant_setScalarCopy(&offsetBuffer->offsets[pos].offsetData.value.value->value,
&p->groupHeader.sequenceNumber, &UA_TYPES[UA_TYPES_UINT16]);
offsetBuffer->offsets[pos].contentType = UA_PUBSUB_OFFSETTYPE_NETWORKMESSAGE_SEQUENCENUMBER;
}
@@ -27418,6 +27142,13 @@ UA_NetworkMessage_calcSizeBinary(UA_NetworkMessage *p, UA_NetworkMessageOffsetBu
if(p->networkMessageType == UA_NETWORKMESSAGE_DATASET) {
size += UA_Byte_calcSizeBinary(&p->payloadHeader.dataSetPayloadHeader.count);
if(p->payloadHeader.dataSetPayloadHeader.dataSetWriterIds != NULL) {
+ if(offsetBuffer && offsetBuffer->RTsubscriberEnabled){
+ size_t pos = offsetBuffer->offsetsSize;
+ if(!increaseOffsetArray(offsetBuffer))
+ return 0;
+ offsetBuffer->offsets[pos].offset = size;
+ offsetBuffer->offsets[pos].contentType = UA_PUBSUB_OFFSETTYPE_DATASETWRITERID;
+ }
size += UA_UInt16_calcSizeBinary(&p->payloadHeader.dataSetPayloadHeader.dataSetWriterIds[0]) *
p->payloadHeader.dataSetPayloadHeader.count;
} else {
@@ -27459,9 +27190,8 @@ UA_NetworkMessage_calcSizeBinary(UA_NetworkMessage *p, UA_NetworkMessageOffsetBu
if(p->securityEnabled) {
size += UA_Byte_calcSizeBinary(&byte);
size += UA_UInt32_calcSizeBinary(&p->securityHeader.securityTokenId);
- size += UA_Byte_calcSizeBinary(&p->securityHeader.nonceLength);
- if(p->securityHeader.nonceLength > 0)
- size += (UA_Byte_calcSizeBinary(&p->securityHeader.messageNonce.data[0]) * p->securityHeader.nonceLength);
+ size += 1; /* UA_Byte_calcSizeBinary(&p->securityHeader.nonceLength); */
+ size += p->securityHeader.messageNonce.length;
if(p->securityHeader.securityFooterEnabled)
size += UA_UInt16_calcSizeBinary(&p->securityHeader.securityFooterSize);
}
@@ -27482,12 +27212,9 @@ UA_NetworkMessage_calcSizeBinary(UA_NetworkMessage *p, UA_NetworkMessageOffsetBu
}
}
- if (p->securityEnabled) {
- if (p->securityHeader.securityFooterEnabled)
+ if(p->securityEnabled) {
+ if(p->securityHeader.securityFooterEnabled)
size += p->securityHeader.securityFooterSize;
-
- if (p->securityHeader.networkMessageSigned)
- size += UA_ByteString_calcSizeBinary(&p->signature);
}
retval = size;
@@ -27495,12 +27222,11 @@ UA_NetworkMessage_calcSizeBinary(UA_NetworkMessage *p, UA_NetworkMessageOffsetBu
}
void
-UA_NetworkMessage_deleteMembers(UA_NetworkMessage* p) {
+UA_NetworkMessage_clear(UA_NetworkMessage* p) {
if(p->promotedFieldsEnabled)
UA_Array_delete(p->promotedFields, p->promotedFieldsSize, &UA_TYPES[UA_TYPES_VARIANT]);
- if(p->securityEnabled && (p->securityHeader.nonceLength > 0))
- UA_ByteString_deleteMembers(&p->securityHeader.messageNonce);
+ UA_ByteString_clear(&p->securityHeader.messageNonce);
if(p->networkMessageType == UA_NETWORKMESSAGE_DATASET) {
if(p->payloadHeaderEnabled) {
@@ -27508,41 +27234,40 @@ UA_NetworkMessage_deleteMembers(UA_NetworkMessage* p) {
UA_Array_delete(p->payloadHeader.dataSetPayloadHeader.dataSetWriterIds,
p->payloadHeader.dataSetPayloadHeader.count, &UA_TYPES[UA_TYPES_UINT16]);
}
-
if(p->payload.dataSetPayload.sizes != NULL) {
UA_Array_delete(p->payload.dataSetPayload.sizes,
p->payloadHeader.dataSetPayloadHeader.count, &UA_TYPES[UA_TYPES_UINT16]);
}
}
- if(p->payload.dataSetPayload.dataSetMessages != NULL) {
+ if(p->payload.dataSetPayload.dataSetMessages) {
UA_Byte count = 1;
if(p->payloadHeaderEnabled)
count = p->payloadHeader.dataSetPayloadHeader.count;
- for (size_t i = 0; i < count; i++)
- UA_DataSetMessage_free(&(p->payload.dataSetPayload.dataSetMessages[i]));
+ for(size_t i = 0; i < count; i++)
+ UA_DataSetMessage_clear(&(p->payload.dataSetPayload.dataSetMessages[i]));
UA_free(p->payload.dataSetPayload.dataSetMessages);
}
}
if(p->securityHeader.securityFooterEnabled && (p->securityHeader.securityFooterSize > 0))
- UA_ByteString_deleteMembers(&p->securityFooter);
+ UA_ByteString_clear(&p->securityFooter);
if(p->messageIdEnabled){
- UA_String_deleteMembers(&p->messageId);
+ UA_String_clear(&p->messageId);
}
if(p->publisherIdEnabled && p->publisherIdType == UA_PUBLISHERDATATYPE_STRING){
- UA_String_deleteMembers(&p->publisherId.publisherIdString);
+ UA_String_clear(&p->publisherId.publisherIdString);
}
memset(p, 0, sizeof(UA_NetworkMessage));
}
void UA_NetworkMessage_delete(UA_NetworkMessage* p) {
- UA_NetworkMessage_deleteMembers(p);
+ UA_NetworkMessage_clear(p);
}
UA_Boolean
@@ -27606,9 +27331,8 @@ UA_DataSetMessageHeader_encodeBinary(const UA_DataSetMessageHeader* src, UA_Byte
v |= DS_MESSAGEHEADER_FLAGS2_ENABLED_MASK;
UA_StatusCode rv = UA_Byte_encodeBinary(&v, bufPos, bufEnd);
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
-
+ UA_CHECK_STATUS(rv, return rv);
+
// DataSetFlags2
if(UA_DataSetMessageHeader_DataSetFlags2Enabled(src)) {
v = (UA_Byte)src->dataSetMessageType;
@@ -27620,63 +27344,96 @@ UA_DataSetMessageHeader_encodeBinary(const UA_DataSetMessageHeader* src, UA_Byte
v |= DS_MESSAGEHEADER_PICOSECONDS_INCLUDED_MASK;
rv = UA_Byte_encodeBinary(&v, bufPos, bufEnd);
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
+ UA_CHECK_STATUS(rv, return rv);
}
// DataSetMessageSequenceNr
if(src->dataSetMessageSequenceNrEnabled) {
rv = UA_UInt16_encodeBinary(&src->dataSetMessageSequenceNr, bufPos, bufEnd);
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
+ UA_CHECK_STATUS(rv, return rv);
}
// Timestamp
if(src->timestampEnabled) {
rv = UA_DateTime_encodeBinary(&(src->timestamp), bufPos, bufEnd); /* UtcTime */
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
+ UA_CHECK_STATUS(rv, return rv);
}
// PicoSeconds
if(src->picoSecondsIncluded) {
rv = UA_UInt16_encodeBinary(&(src->picoSeconds), bufPos, bufEnd);
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
+ UA_CHECK_STATUS(rv, return rv);
}
// Status
if(src->statusEnabled) {
rv = UA_UInt16_encodeBinary(&(src->status), bufPos, bufEnd);
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
+ UA_CHECK_STATUS(rv, return rv);
}
// ConfigVersionMajorVersion
if(src->configVersionMajorVersionEnabled) {
rv = UA_UInt32_encodeBinary(&(src->configVersionMajorVersion), bufPos, bufEnd);
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
+ UA_CHECK_STATUS(rv, return rv);
}
// ConfigVersionMinorVersion
if(src->configVersionMinorVersionEnabled) {
rv = UA_UInt32_encodeBinary(&(src->configVersionMinorVersion), bufPos, bufEnd);
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
+ UA_CHECK_STATUS(rv, return rv);
}
return UA_STATUSCODE_GOOD;
}
+#ifdef UA_ENABLE_PUBSUB_ENCRYPTION
+
+UA_StatusCode
+UA_NetworkMessage_signEncrypt(UA_NetworkMessage *nm, UA_MessageSecurityMode securityMode,
+ UA_PubSubSecurityPolicy *policy, void *policyContext,
+ UA_Byte *messageStart, UA_Byte *encryptStart,
+ UA_Byte *sigStart) {
+ UA_StatusCode res = UA_STATUSCODE_GOOD;
+
+ /* Encrypt the payload */
+ if(securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) {
+ /* Set the temporary MessageNonce in the SecurityPolicy */
+ res = policy->setMessageNonce(policyContext, &nm->securityHeader.messageNonce);
+ UA_CHECK_STATUS(res, return res);
+
+ /* The encryption is done in-place, no need to encode again */
+ UA_ByteString encryptBuf;
+ encryptBuf.data = encryptStart;
+ encryptBuf.length = (uintptr_t)sigStart - (uintptr_t)encryptStart;
+ res = policy->symmetricModule.cryptoModule.encryptionAlgorithm.
+ encrypt(policyContext, &encryptBuf);
+ UA_CHECK_STATUS(res, return res);
+ }
+
+ /* Sign the entire message */
+ if(securityMode == UA_MESSAGESECURITYMODE_SIGN ||
+ securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) {
+ UA_ByteString sigBuf;
+ sigBuf.length = (uintptr_t)sigStart - (uintptr_t)messageStart;
+ sigBuf.data = messageStart;
+ size_t sigSize = policy->symmetricModule.cryptoModule.
+ signatureAlgorithm.getLocalSignatureSize(policyContext);
+ UA_ByteString sig = {sigSize, sigStart};
+ res = policy->symmetricModule.cryptoModule.
+ signatureAlgorithm.sign(policyContext, &sigBuf, &sig);
+ }
+
+ return res;
+}
+#endif
+
UA_StatusCode
UA_DataSetMessageHeader_decodeBinary(const UA_ByteString *src, size_t *offset,
UA_DataSetMessageHeader* dst) {
memset(dst, 0, sizeof(UA_DataSetMessageHeader));
UA_Byte v = 0;
UA_StatusCode rv = UA_Byte_decodeBinary(src, offset, &v);
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
+ UA_CHECK_STATUS(rv, return rv);
UA_Byte v2 = v & DS_MESSAGEHEADER_FIELD_ENCODING_MASK;
v2 = (UA_Byte)(v2 >> DS_MH_SHIFT_LEN);
@@ -27700,9 +27457,8 @@ UA_DataSetMessageHeader_decodeBinary(const UA_ByteString *src, size_t *offset,
if((v & DS_MESSAGEHEADER_FLAGS2_ENABLED_MASK) != 0) {
v = 0;
rv = UA_Byte_decodeBinary(src, offset, &v);
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
-
+ UA_CHECK_STATUS(rv, return rv);
+
dst->dataSetMessageType = (UA_DataSetMessageType)(v & DS_MESSAGEHEADER_DS_MESSAGE_TYPE_MASK);
if((v & DS_MESSAGEHEADER_TIMESTAMP_ENABLED_MASK) != 0)
@@ -27717,48 +27473,42 @@ UA_DataSetMessageHeader_decodeBinary(const UA_ByteString *src, size_t *offset,
if(dst->dataSetMessageSequenceNrEnabled) {
rv = UA_UInt16_decodeBinary(src, offset, &dst->dataSetMessageSequenceNr);
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
+ UA_CHECK_STATUS(rv, return rv);
} else {
dst->dataSetMessageSequenceNr = 0;
}
if(dst->timestampEnabled) {
rv = UA_DateTime_decodeBinary(src, offset, &dst->timestamp); /* UtcTime */
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
+ UA_CHECK_STATUS(rv, return rv);
} else {
dst->timestamp = 0;
}
if(dst->picoSecondsIncluded) {
rv = UA_UInt16_decodeBinary(src, offset, &dst->picoSeconds);
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
+ UA_CHECK_STATUS(rv, return rv);
} else {
dst->picoSeconds = 0;
}
if(dst->statusEnabled) {
rv = UA_UInt16_decodeBinary(src, offset, &dst->status);
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
+ UA_CHECK_STATUS(rv, return rv);
} else {
dst->status = 0;
}
if(dst->configVersionMajorVersionEnabled) {
rv = UA_UInt32_decodeBinary(src, offset, &dst->configVersionMajorVersion);
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
+ UA_CHECK_STATUS(rv, return rv);
} else {
dst->configVersionMajorVersion = 0;
}
if(dst->configVersionMinorVersionEnabled) {
rv = UA_UInt32_decodeBinary(src, offset, &dst->configVersionMinorVersion);
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
+ UA_CHECK_STATUS(rv, return rv);
} else {
dst->configVersionMinorVersion = 0;
}
@@ -27768,7 +27518,7 @@ UA_DataSetMessageHeader_decodeBinary(const UA_ByteString *src, size_t *offset,
size_t
UA_DataSetMessageHeader_calcSizeBinary(const UA_DataSetMessageHeader* p) {
- UA_Byte byte;
+ UA_Byte byte = 0;
size_t size = UA_Byte_calcSizeBinary(&byte); // DataSetMessage Type + Flags
if(UA_DataSetMessageHeader_DataSetFlags2Enabled(p))
size += UA_Byte_calcSizeBinary(&byte);
@@ -27798,59 +27548,54 @@ UA_StatusCode
UA_DataSetMessage_encodeBinary(const UA_DataSetMessage* src, UA_Byte **bufPos,
const UA_Byte *bufEnd) {
UA_StatusCode rv = UA_DataSetMessageHeader_encodeBinary(&src->header, bufPos, bufEnd);
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
+ UA_CHECK_STATUS(rv, return rv);
if(src->header.dataSetMessageType == UA_DATASETMESSAGE_DATAKEYFRAME) {
if(src->header.fieldEncoding != UA_FIELDENCODING_RAWDATA) {
rv = UA_UInt16_encodeBinary(&(src->data.keyFrameData.fieldCount), bufPos, bufEnd);
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
+ UA_CHECK_STATUS(rv, return rv);
}
-
if(src->header.fieldEncoding == UA_FIELDENCODING_VARIANT) {
for (UA_UInt16 i = 0; i < src->data.keyFrameData.fieldCount; i++) {
rv = UA_Variant_encodeBinary(&(src->data.keyFrameData.dataSetFields[i].value), bufPos, bufEnd);
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
+ UA_CHECK_STATUS(rv, return rv);
}
} else if(src->header.fieldEncoding == UA_FIELDENCODING_RAWDATA) {
- return UA_STATUSCODE_BADNOTIMPLEMENTED;
+ for (UA_UInt16 i = 0; i < src->data.keyFrameData.fieldCount; i++) {
+ rv = UA_encodeBinaryInternal(src->data.keyFrameData.dataSetFields[i].value.data,
+ src->data.keyFrameData.dataSetFields[i].value.type,
+ bufPos, &bufEnd, NULL, NULL);
+ UA_CHECK_STATUS(rv, return rv);
+ }
} else if(src->header.fieldEncoding == UA_FIELDENCODING_DATAVALUE) {
for (UA_UInt16 i = 0; i < src->data.keyFrameData.fieldCount; i++) {
rv = UA_DataValue_encodeBinary(&(src->data.keyFrameData.dataSetFields[i]), bufPos, bufEnd);
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
+ UA_CHECK_STATUS(rv, return rv);
}
}
} else if(src->header.dataSetMessageType == UA_DATASETMESSAGE_DATADELTAFRAME) {
// Encode Delta Frame
// Here the FieldCount is always present
rv = UA_UInt16_encodeBinary(&(src->data.keyFrameData.fieldCount), bufPos, bufEnd);
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
+ UA_CHECK_STATUS(rv, return rv);
if(src->header.fieldEncoding == UA_FIELDENCODING_VARIANT) {
for (UA_UInt16 i = 0; i < src->data.deltaFrameData.fieldCount; i++) {
rv = UA_UInt16_encodeBinary(&(src->data.deltaFrameData.deltaFrameFields[i].fieldIndex), bufPos, bufEnd);
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
-
+ UA_CHECK_STATUS(rv, return rv);
+
rv = UA_Variant_encodeBinary(&(src->data.deltaFrameData.deltaFrameFields[i].fieldValue.value), bufPos, bufEnd);
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
+ UA_CHECK_STATUS(rv, return rv);
}
} else if(src->header.fieldEncoding == UA_FIELDENCODING_RAWDATA) {
return UA_STATUSCODE_BADNOTIMPLEMENTED;
} else if(src->header.fieldEncoding == UA_FIELDENCODING_DATAVALUE) {
for (UA_UInt16 i = 0; i < src->data.deltaFrameData.fieldCount; i++) {
rv = UA_UInt16_encodeBinary(&(src->data.deltaFrameData.deltaFrameFields[i].fieldIndex), bufPos, bufEnd);
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
+ UA_CHECK_STATUS(rv, return rv);
rv = UA_DataValue_encodeBinary(&(src->data.deltaFrameData.deltaFrameFields[i].fieldValue), bufPos, bufEnd);
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
+ UA_CHECK_STATUS(rv, return rv);
}
}
} else if(src->header.dataSetMessageType != UA_DATASETMESSAGE_KEEPALIVE) {
@@ -27862,76 +27607,97 @@ UA_DataSetMessage_encodeBinary(const UA_DataSetMessage* src, UA_Byte **bufPos,
}
UA_StatusCode
-UA_DataSetMessage_decodeBinary(const UA_ByteString *src, size_t *offset, UA_DataSetMessage* dst) {
+UA_DataSetMessage_decodeBinary(const UA_ByteString *src, size_t *offset, UA_DataSetMessage* dst, UA_UInt16 dsmSize) {
+ size_t initialOffset = *offset;
memset(dst, 0, sizeof(UA_DataSetMessage));
UA_StatusCode rv = UA_DataSetMessageHeader_decodeBinary(src, offset, &dst->header);
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
+ UA_CHECK_STATUS(rv, return rv);
if(dst->header.dataSetMessageType == UA_DATASETMESSAGE_DATAKEYFRAME) {
- if(dst->header.fieldEncoding != UA_FIELDENCODING_RAWDATA) {
- rv = UA_UInt16_decodeBinary(src, offset, &dst->data.keyFrameData.fieldCount);
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
-
- if(dst->header.fieldEncoding == UA_FIELDENCODING_VARIANT) {
+ switch(dst->header.fieldEncoding) {
+ case UA_FIELDENCODING_VARIANT:
+ {
+ rv = UA_UInt16_decodeBinary(src, offset, &dst->data.keyFrameData.fieldCount);
+ UA_CHECK_STATUS(rv, return rv);
dst->data.keyFrameData.dataSetFields =
(UA_DataValue *)UA_Array_new(dst->data.keyFrameData.fieldCount, &UA_TYPES[UA_TYPES_DATAVALUE]);
for (UA_UInt16 i = 0; i < dst->data.keyFrameData.fieldCount; i++) {
UA_DataValue_init(&dst->data.keyFrameData.dataSetFields[i]);
rv = UA_Variant_decodeBinary(src, offset, &dst->data.keyFrameData.dataSetFields[i].value);
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
+ UA_CHECK_STATUS(rv, return rv);
+
dst->data.keyFrameData.dataSetFields[i].hasValue = true;
}
- } else if(dst->header.fieldEncoding == UA_FIELDENCODING_RAWDATA) {
- return UA_STATUSCODE_BADNOTIMPLEMENTED;
- } else if(dst->header.fieldEncoding == UA_FIELDENCODING_DATAVALUE) {
+ break;
+ }
+ case UA_FIELDENCODING_DATAVALUE:
+ {
+ rv = UA_UInt16_decodeBinary(src, offset, &dst->data.keyFrameData.fieldCount);
+ UA_CHECK_STATUS(rv, return rv);
dst->data.keyFrameData.dataSetFields =
(UA_DataValue *)UA_Array_new(dst->data.keyFrameData.fieldCount, &UA_TYPES[UA_TYPES_DATAVALUE]);
for (UA_UInt16 i = 0; i < dst->data.keyFrameData.fieldCount; i++) {
rv = UA_DataValue_decodeBinary(src, offset, &(dst->data.keyFrameData.dataSetFields[i]));
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
+ UA_CHECK_STATUS(rv, return rv);
}
+ break;
}
+ case UA_FIELDENCODING_RAWDATA:
+ {
+ dst->data.keyFrameData.rawFields.data = &src->data[*offset];
+ dst->data.keyFrameData.rawFields.length = dsmSize;
+ if(dsmSize == 0){
+ //TODO calculate the length of the DSM-Payload for a single DSM
+ //Problem: Size is not set and MetaData information are needed.
+ //Increase offset to avoid endless chunk loop. Needs to be fixed when
+ //pubsub security footer and signatur is enabled.
+ *offset += 1500;
+ } else {
+ *offset += (dsmSize - (*offset - initialOffset));
+ }
+ break;
+ }
+ default:
+ return UA_STATUSCODE_BADINTERNALERROR;
}
} else if(dst->header.dataSetMessageType == UA_DATASETMESSAGE_DATADELTAFRAME) {
- if(dst->header.fieldEncoding != UA_FIELDENCODING_RAWDATA) {
- rv = UA_UInt16_decodeBinary(src, offset, &dst->data.deltaFrameData.fieldCount);
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
-
- if(dst->header.fieldEncoding == UA_FIELDENCODING_VARIANT) {
+ switch(dst->header.fieldEncoding) {
+ case UA_FIELDENCODING_VARIANT: {
+ rv = UA_UInt16_decodeBinary(src, offset, &dst->data.deltaFrameData.fieldCount);
+ UA_CHECK_STATUS(rv, return rv);
size_t memsize = sizeof(UA_DataSetMessage_DeltaFrameField) * dst->data.deltaFrameData.fieldCount;
dst->data.deltaFrameData.deltaFrameFields = (UA_DataSetMessage_DeltaFrameField*)UA_malloc(memsize);
for (UA_UInt16 i = 0; i < dst->data.deltaFrameData.fieldCount; i++) {
rv = UA_UInt16_decodeBinary(src, offset, &dst->data.deltaFrameData.deltaFrameFields[i].fieldIndex);
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
-
+ UA_CHECK_STATUS(rv, return rv);
+
UA_DataValue_init(&dst->data.deltaFrameData.deltaFrameFields[i].fieldValue);
rv = UA_Variant_decodeBinary(src, offset, &dst->data.deltaFrameData.deltaFrameFields[i].fieldValue.value);
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
+ UA_CHECK_STATUS(rv, return rv);
dst->data.deltaFrameData.deltaFrameFields[i].fieldValue.hasValue = true;
}
- } else if(dst->header.fieldEncoding == UA_FIELDENCODING_RAWDATA) {
- return UA_STATUSCODE_BADNOTIMPLEMENTED;
- } else if(dst->header.fieldEncoding == UA_FIELDENCODING_DATAVALUE) {
+ break;
+ }
+ case UA_FIELDENCODING_DATAVALUE: {
+ rv = UA_UInt16_decodeBinary(src, offset, &dst->data.deltaFrameData.fieldCount);
+ UA_CHECK_STATUS(rv, return rv);
size_t memsize = sizeof(UA_DataSetMessage_DeltaFrameField) * dst->data.deltaFrameData.fieldCount;
dst->data.deltaFrameData.deltaFrameFields = (UA_DataSetMessage_DeltaFrameField*)UA_malloc(memsize);
for (UA_UInt16 i = 0; i < dst->data.deltaFrameData.fieldCount; i++) {
rv = UA_UInt16_decodeBinary(src, offset, &dst->data.deltaFrameData.deltaFrameFields[i].fieldIndex);
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
-
+ UA_CHECK_STATUS(rv, return rv);
+
rv = UA_DataValue_decodeBinary(src, offset, &(dst->data.deltaFrameData.deltaFrameFields[i].fieldValue));
- if(rv != UA_STATUSCODE_GOOD)
- return rv;
+ UA_CHECK_STATUS(rv, return rv);
}
+ break;
}
+ case UA_FIELDENCODING_RAWDATA: {
+ return UA_STATUSCODE_BADNOTIMPLEMENTED;
+ }
+ default:
+ return UA_STATUSCODE_BADINTERNALERROR;
}
} else if(dst->header.dataSetMessageType != UA_DATASETMESSAGE_KEEPALIVE) {
return UA_STATUSCODE_BADNOTIMPLEMENTED;
@@ -27944,7 +27710,20 @@ UA_DataSetMessage_decodeBinary(const UA_ByteString *src, size_t *offset, UA_Data
size_t
UA_DataSetMessage_calcSizeBinary(UA_DataSetMessage* p, UA_NetworkMessageOffsetBuffer *offsetBuffer, size_t currentOffset) {
size_t size = currentOffset;
- UA_Byte byte;
+
+ if (offsetBuffer) {
+ size_t pos = offsetBuffer->offsetsSize;
+ if(!increaseOffsetArray(offsetBuffer))
+ return 0;
+ offsetBuffer->offsets[pos].offset = size;
+ offsetBuffer->offsets[pos].offsetData.value.value = UA_DataValue_new();
+ UA_DataValue_init(offsetBuffer->offsets[pos].offsetData.value.value);
+ UA_Variant_setScalar(&offsetBuffer->offsets[pos].offsetData.value.value->value,
+ &p->header.fieldEncoding, &UA_TYPES[UA_TYPES_UINT32]);
+ offsetBuffer->offsets[pos].contentType = UA_PUBSUB_OFFSETTYPE_NETWORKMESSAGE_FIELDENCDODING;
+ }
+
+ UA_Byte byte = 0;
size += UA_Byte_calcSizeBinary(&byte); // DataSetMessage Type + Flags
if(UA_DataSetMessageHeader_DataSetFlags2Enabled(&p->header))
size += UA_Byte_calcSizeBinary(&byte);
@@ -27957,7 +27736,7 @@ UA_DataSetMessage_calcSizeBinary(UA_DataSetMessage* p, UA_NetworkMessageOffsetBu
offsetBuffer->offsets[pos].offset = size;
offsetBuffer->offsets[pos].offsetData.value.value = UA_DataValue_new();
UA_DataValue_init(offsetBuffer->offsets[pos].offsetData.value.value);
- UA_Variant_setScalar(&offsetBuffer->offsets[pos].offsetData.value.value->value,
+ UA_Variant_setScalarCopy(&offsetBuffer->offsets[pos].offsetData.value.value->value,
&p->header.dataSetMessageSequenceNr, &UA_TYPES[UA_TYPES_UINT16]);
offsetBuffer->offsets[pos].contentType = UA_PUBSUB_OFFSETTYPE_DATASETMESSAGE_SEQUENCENUMBER;
}
@@ -27981,10 +27760,8 @@ UA_DataSetMessage_calcSizeBinary(UA_DataSetMessage* p, UA_NetworkMessageOffsetBu
if(p->header.dataSetMessageType == UA_DATASETMESSAGE_DATAKEYFRAME) {
if(p->header.fieldEncoding != UA_FIELDENCODING_RAWDATA){
- //TODO clarify RT and Rawdata behavior
size += UA_calcSizeBinary(&p->data.keyFrameData.fieldCount, &UA_TYPES[UA_TYPES_UINT16]);
}
-
if(p->header.fieldEncoding == UA_FIELDENCODING_VARIANT) {
for (UA_UInt16 i = 0; i < p->data.keyFrameData.fieldCount; i++){
if (offsetBuffer) {
@@ -27994,16 +27771,35 @@ UA_DataSetMessage_calcSizeBinary(UA_DataSetMessage* p, UA_NetworkMessageOffsetBu
offsetBuffer->offsets[pos].offset = size;
offsetBuffer->offsets[pos].contentType = UA_PUBSUB_OFFSETTYPE_PAYLOAD_VARIANT;
//TODO check value source and alloc!
+ //offsetBuffer->offsets[pos].offsetData.value.value = p->data.keyFrameData.dataSetFields;
offsetBuffer->offsets[pos].offsetData.value.value = UA_DataValue_new();
UA_Variant_setScalar(&offsetBuffer->offsets[pos].offsetData.value.value->value,
p->data.keyFrameData.dataSetFields[i].value.data,
p->data.keyFrameData.dataSetFields[i].value.type);
- //offsetBuffer->offsets[pos].offsetData.value.value->value = p->data.keyFrameData.dataSetFields->value;
+ offsetBuffer->offsets[pos].offsetData.value.value->value.storageType = UA_VARIANT_DATA_NODELETE;
}
size += UA_calcSizeBinary(&p->data.keyFrameData.dataSetFields[i].value, &UA_TYPES[UA_TYPES_VARIANT]);
}
} else if(p->header.fieldEncoding == UA_FIELDENCODING_RAWDATA) {
- // not implemented
+ for (UA_UInt16 i = 0; i < p->data.keyFrameData.fieldCount; i++){
+ if (offsetBuffer) {
+ size_t pos = offsetBuffer->offsetsSize;
+ if(!increaseOffsetArray(offsetBuffer))
+ return 0;
+ offsetBuffer->offsets[pos].offset = size;
+ offsetBuffer->offsets[pos].contentType = UA_PUBSUB_OFFSETTYPE_PAYLOAD_RAW;
+ offsetBuffer->offsets[pos].offsetData.value.value = UA_DataValue_new();
+ //init offset buffer with the latest value
+ UA_Variant_setScalar(&offsetBuffer->offsets[pos].offsetData.value.value->value,
+ p->data.keyFrameData.dataSetFields[i].value.data,
+ p->data.keyFrameData.dataSetFields[i].value.type);
+ offsetBuffer->offsets[pos].offsetData.value.value->value.storageType = UA_VARIANT_DATA_NODELETE;
+ //count the memory size of the specific field
+ offsetBuffer->rawMessageLength += p->data.keyFrameData.dataSetFields[i].value.type->memSize;
+ }
+ size += UA_calcSizeBinary(p->data.keyFrameData.dataSetFields[i].value.data,
+ p->data.keyFrameData.dataSetFields[i].value.type);
+ }
} else if(p->header.fieldEncoding == UA_FIELDENCODING_DATAVALUE) {
for (UA_UInt16 i = 0; i < p->data.keyFrameData.fieldCount; i++) {
if (offsetBuffer) {
@@ -28041,23 +27837,28 @@ UA_DataSetMessage_calcSizeBinary(UA_DataSetMessage* p, UA_NetworkMessageOffsetBu
return size;
}
-void UA_DataSetMessage_free(const UA_DataSetMessage* p) {
+void
+UA_DataSetMessage_clear(const UA_DataSetMessage* p) {
if(p->header.dataSetMessageType == UA_DATASETMESSAGE_DATAKEYFRAME) {
- if(p->data.keyFrameData.dataSetFields != NULL)
- UA_Array_delete(p->data.keyFrameData.dataSetFields, p->data.keyFrameData.fieldCount,
+ if(p->data.keyFrameData.dataSetFields != NULL) {
+ UA_Array_delete(p->data.keyFrameData.dataSetFields,
+ p->data.keyFrameData.fieldCount,
&UA_TYPES[UA_TYPES_DATAVALUE]);
+ }
+
/* Json keys */
if(p->data.keyFrameData.fieldNames != NULL){
- UA_Array_delete(p->data.keyFrameData.fieldNames, p->data.keyFrameData.fieldCount,
+ UA_Array_delete(p->data.keyFrameData.fieldNames,
+ p->data.keyFrameData.fieldCount,
&UA_TYPES[UA_TYPES_STRING]);
}
} else if(p->header.dataSetMessageType == UA_DATASETMESSAGE_DATADELTAFRAME) {
if(p->data.deltaFrameData.deltaFrameFields != NULL) {
for(UA_UInt16 i = 0; i < p->data.deltaFrameData.fieldCount; i++) {
if(p->header.fieldEncoding == UA_FIELDENCODING_DATAVALUE) {
- UA_DataValue_deleteMembers(&p->data.deltaFrameData.deltaFrameFields[i].fieldValue);
+ UA_DataValue_clear(&p->data.deltaFrameData.deltaFrameFields[i].fieldValue);
} else if(p->header.fieldEncoding == UA_FIELDENCODING_VARIANT) {
- UA_Variant_deleteMembers(&p->data.deltaFrameData.deltaFrameFields[i].fieldValue.value);
+ UA_Variant_clear(&p->data.deltaFrameData.deltaFrameFields[i].fieldValue.value);
}
}
UA_free(p->data.deltaFrameData.deltaFrameFields);
@@ -28066,7 +27867,7 @@ void UA_DataSetMessage_free(const UA_DataSetMessage* p) {
}
#endif /* UA_ENABLE_PUBSUB */
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/src/pubsub/ua_pubsub_writer.c" ***********************************/
+/**** amalgamated original file "/src/pubsub/ua_pubsub_writer.c" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -28074,7 +27875,10 @@ void UA_DataSetMessage_free(const UA_DataSetMessage* p) {
*
* Copyright (c) 2017-2019 Fraunhofer IOSB (Author: Andreas Ebner)
* Copyright (c) 2019 Fraunhofer IOSB (Author: Julius Pfrommer)
- * Copyright (c) 2019 Kalycito Infotech Private Limited
+ * Copyright (c) 2019-2021 Kalycito Infotech Private Limited
+ * Copyright (c) 2020 Yannick Wallerer, Siemens AG
+ * Copyright (c) 2020 Thomas Fischer, Siemens AG
+ * Copyright (c) 2021 Fraunhofer IOSB (Author: Jan Hermes)
*/
@@ -28087,22 +27891,9 @@ void UA_DataSetMessage_free(const UA_DataSetMessage* p) {
#ifdef UA_ENABLE_PUBSUB_DELTAFRAMES
#endif
-#define UA_MAX_STACKBUF 512 /* Max size of network messages on the stack */
-
/* Forward declaration */
static void
-UA_WriterGroup_clear(UA_Server *server, UA_WriterGroup *writerGroup);
-static void
UA_DataSetField_clear(UA_DataSetField *field);
-static UA_StatusCode
-generateNetworkMessage(UA_PubSubConnection *connection, UA_WriterGroup *wg,
- UA_DataSetMessage *dsm, UA_UInt16 *writerIds, UA_Byte dsmCount,
- UA_ExtensionObject *messageSettings,
- UA_ExtensionObject *transportSettings,
- UA_NetworkMessage *networkMessage);
-static UA_StatusCode
-UA_DataSetWriter_generateDataSetMessage(UA_Server *server, UA_DataSetMessage *dataSetMessage,
- UA_DataSetWriter *dataSetWriter);
/**********************************************/
/* Connection */
@@ -28116,7 +27907,8 @@ UA_PubSubConnectionConfig_copy(const UA_PubSubConnectionConfig *src,
res |= UA_String_copy(&src->name, &dst->name);
res |= UA_Variant_copy(&src->address, &dst->address);
res |= UA_String_copy(&src->transportProfileUri, &dst->transportProfileUri);
- res |= UA_Variant_copy(&src->connectionTransportSettings, &dst->connectionTransportSettings);
+ res |= UA_Variant_copy(&src->connectionTransportSettings,
+ &dst->connectionTransportSettings);
if(src->connectionPropertiesSize > 0) {
dst->connectionProperties = (UA_KeyValuePair *)
UA_calloc(src->connectionPropertiesSize, sizeof(UA_KeyValuePair));
@@ -28141,12 +27933,10 @@ UA_Server_getPubSubConnectionConfig(UA_Server *server, const UA_NodeId connectio
UA_PubSubConnectionConfig *config) {
if(!config)
return UA_STATUSCODE_BADINVALIDARGUMENT;
-
UA_PubSubConnection *currentPubSubConnection =
UA_PubSubConnection_findConnectionbyId(server, connection);
if(!currentPubSubConnection)
return UA_STATUSCODE_BADNOTFOUND;
-
return UA_PubSubConnectionConfig_copy(currentPubSubConnection->config, config);
}
@@ -28193,306 +27983,23 @@ UA_PubSubConnection_clear(UA_Server *server, UA_PubSubConnection *connection) {
UA_free(connection->config);
}
-UA_StatusCode
-UA_PubSubConnection_regist(UA_Server *server, UA_NodeId *connectionIdentifier) {
- UA_PubSubConnection *connection =
- UA_PubSubConnection_findConnectionbyId(server, *connectionIdentifier);
- if(!connection)
- return UA_STATUSCODE_BADNOTFOUND;
-
- UA_StatusCode retval = connection->channel->regist(connection->channel, NULL, NULL);
- if(retval != UA_STATUSCODE_GOOD) {
- UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
- "register channel failed: 0x%" PRIx32 "!", retval);
- }
- return retval;
-}
-
-UA_StatusCode
-UA_Server_addWriterGroup(UA_Server *server, const UA_NodeId connection,
- const UA_WriterGroupConfig *writerGroupConfig,
- UA_NodeId *writerGroupIdentifier) {
- if(!writerGroupConfig)
- return UA_STATUSCODE_BADINVALIDARGUMENT;
- //search the connection by the given connectionIdentifier
- UA_PubSubConnection *currentConnectionContext =
- UA_PubSubConnection_findConnectionbyId(server, connection);
- if(!currentConnectionContext)
- return UA_STATUSCODE_BADNOTFOUND;
-
- if(currentConnectionContext->config->configurationFrozen){
- UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
- "Adding WriterGroup failed. PubSubConnection is frozen.");
- return UA_STATUSCODE_BADCONFIGURATIONERROR;
- }
-
- /* Validate messageSettings type */
- if (writerGroupConfig->messageSettings.content.decoded.type) {
- if (writerGroupConfig->encodingMimeType == UA_PUBSUB_ENCODING_JSON &&
- (writerGroupConfig->messageSettings.encoding != UA_EXTENSIONOBJECT_DECODED
- || writerGroupConfig->messageSettings.content.decoded.type->typeIndex != UA_TYPES_JSONWRITERGROUPMESSAGEDATATYPE) ) {
- return UA_STATUSCODE_BADTYPEMISMATCH;
- }
-
- if (writerGroupConfig->encodingMimeType == UA_PUBSUB_ENCODING_UADP &&
- (writerGroupConfig->messageSettings.encoding != UA_EXTENSIONOBJECT_DECODED
- || writerGroupConfig->messageSettings.content.decoded.type->typeIndex != UA_TYPES_UADPWRITERGROUPMESSAGEDATATYPE) ) {
- return UA_STATUSCODE_BADTYPEMISMATCH;
- }
- }
-
-
- //allocate memory for new WriterGroup
- UA_WriterGroup *newWriterGroup = (UA_WriterGroup *) UA_calloc(1, sizeof(UA_WriterGroup));
- if(!newWriterGroup)
- return UA_STATUSCODE_BADOUTOFMEMORY;
-
- newWriterGroup->linkedConnection = currentConnectionContext;
- UA_PubSubManager_generateUniqueNodeId(server, &newWriterGroup->identifier);
- if(writerGroupIdentifier)
- UA_NodeId_copy(&newWriterGroup->identifier, writerGroupIdentifier);
-
- //deep copy of the config
- UA_WriterGroupConfig tmpWriterGroupConfig;
- UA_StatusCode retVal = UA_WriterGroupConfig_copy(writerGroupConfig, &tmpWriterGroupConfig);
-
- if(!tmpWriterGroupConfig.messageSettings.content.decoded.type) {
- UA_UadpWriterGroupMessageDataType *wgm = UA_UadpWriterGroupMessageDataType_new();
- tmpWriterGroupConfig.messageSettings.content.decoded.data = wgm;
- tmpWriterGroupConfig.messageSettings.content.decoded.type =
- &UA_TYPES[UA_TYPES_UADPWRITERGROUPMESSAGEDATATYPE];
- tmpWriterGroupConfig.messageSettings.encoding = UA_EXTENSIONOBJECT_DECODED;
- }
- newWriterGroup->config = tmpWriterGroupConfig;
- LIST_INSERT_HEAD(&currentConnectionContext->writerGroups, newWriterGroup, listEntry);
-#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL
- addWriterGroupRepresentation(server, newWriterGroup);
-#endif
- return retVal;
-}
-
-UA_StatusCode
-UA_Server_removeWriterGroup(UA_Server *server, const UA_NodeId writerGroup) {
- UA_WriterGroup *wg = UA_WriterGroup_findWGbyId(server, writerGroup);
- if(!wg)
- return UA_STATUSCODE_BADNOTFOUND;
-
- if(wg->config.configurationFrozen){
- UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
- "Delete WriterGroup failed. WriterGroup is frozen.");
- return UA_STATUSCODE_BADCONFIGURATIONERROR;
- }
-
- UA_PubSubConnection *connection = wg->linkedConnection;
- if(!connection)
- return UA_STATUSCODE_BADNOTFOUND;
-
- if(connection->config->configurationFrozen){
- UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
- "Delete WriterGroup failed. PubSubConnection is frozen.");
- return UA_STATUSCODE_BADCONFIGURATIONERROR;
- }
- if(wg->state == UA_PUBSUBSTATE_OPERATIONAL){
- //unregister the publish callback
- UA_PubSubManager_removeRepeatedPubSubCallback(server, wg->publishCallbackId);
- }
-#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL
- removeGroupRepresentation(server, wg);
-#endif
-
- UA_WriterGroup_clear(server, wg);
- LIST_REMOVE(wg, listEntry);
- UA_free(wg);
- return UA_STATUSCODE_GOOD;
-}
-
-UA_StatusCode
-UA_Server_freezeWriterGroupConfiguration(UA_Server *server, const UA_NodeId writerGroup) {
- UA_WriterGroup *wg = UA_WriterGroup_findWGbyId(server, writerGroup);
- if(!wg)
- return UA_STATUSCODE_BADNOTFOUND;
-
- //PubSubConnection freezeCounter++
- UA_PubSubConnection *pubSubConnection = wg->linkedConnection;
- pubSubConnection->configurationFreezeCounter++;
- pubSubConnection->config->configurationFrozen = UA_TRUE;
- //WriterGroup freeze
- wg->config.configurationFrozen = UA_TRUE;
- //DataSetWriter freeze
- UA_DataSetWriter *dataSetWriter;
- LIST_FOREACH(dataSetWriter, &wg->writers, listEntry){
- dataSetWriter->config.configurationFrozen = UA_TRUE;
- //PublishedDataSet freezeCounter++
- UA_PublishedDataSet *publishedDataSet =
- UA_PublishedDataSet_findPDSbyId(server, dataSetWriter->connectedDataSet);
- publishedDataSet->configurationFreezeCounter++;
- publishedDataSet->config.configurationFrozen = UA_TRUE;
- //DataSetFields freeze
- UA_DataSetField *dataSetField;
- TAILQ_FOREACH(dataSetField, &publishedDataSet->fields, listEntry){
- dataSetField->config.configurationFrozen = UA_TRUE;
- }
- }
-
- if(wg->config.rtLevel == UA_PUBSUB_RT_FIXED_SIZE){
- size_t dsmCount = 0;
- if(wg->config.encodingMimeType != UA_PUBSUB_ENCODING_UADP) {
- UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
- "PubSub-RT configuration fail: Non-RT capable encoding.");
- return UA_STATUSCODE_BADNOTSUPPORTED;
- }
- //TODO Clarify: should we only allow = maxEncapsulatedDataSetMessageCount == 1 with RT?
- //TODO Clarify: Behaviour if the finale size is more than MTU
- /* Generate data set messages */
- UA_STACKARRAY(UA_UInt16, dsWriterIds, wg->writersCount);
- UA_STACKARRAY(UA_DataSetMessage, dsmStore, wg->writersCount);
- UA_DataSetWriter *dsw;
- LIST_FOREACH(dsw, &wg->writers, listEntry) {
- /* Find the dataset */
- UA_PublishedDataSet *pds =
- UA_PublishedDataSet_findPDSbyId(server, dsw->connectedDataSet);
- if(!pds) {
- UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
- "PubSub Publish: PublishedDataSet not found");
- continue;
- }
- if(pds->promotedFieldsCount > 0) {
- UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
- "PubSub-RT configuration fail: PDS contains promoted fields.");
- return UA_STATUSCODE_BADNOTSUPPORTED;
- }
- UA_DataSetField *dsf;
- TAILQ_FOREACH(dsf, &pds->fields, listEntry){
- if(!dsf->config.field.variable.staticValueSourceEnabled){
- UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
- "PubSub-RT configuration fail: PDS contains variables with dynamic length types.");
- return UA_STATUSCODE_BADNOTSUPPORTED;
- }
- if((UA_NodeId_equal(&dsf->fieldMetaData.dataType, &UA_TYPES[UA_TYPES_STRING].typeId) ||
- UA_NodeId_equal(&dsf->fieldMetaData.dataType,
- &UA_TYPES[UA_TYPES_BYTESTRING].typeId)) &&
- dsf->fieldMetaData.maxStringLength == 0) {
- UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
- "PubSub-RT configuration fail: "
- "PDS contains String/ByteString with dynamic length.");
- return UA_STATUSCODE_BADNOTSUPPORTED;
- } else if(!UA_DataType_isNumeric(UA_findDataType(&dsf->fieldMetaData.dataType))){
- UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
- "PubSub-RT configuration fail: "
- "PDS contains variable with dynamic size.");
- return UA_STATUSCODE_BADNOTSUPPORTED;
- }
- }
- /* Generate the DSM */
- UA_StatusCode res =
- UA_DataSetWriter_generateDataSetMessage(server, &dsmStore[dsmCount], dsw);
- if(res != UA_STATUSCODE_GOOD) {
- UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
- "PubSub RT Offset calculation: DataSetMessage buffering failed");
- continue;
- }
- dsWriterIds[dsmCount] = dsw->config.dataSetWriterId;
- dsmCount++;
- }
- UA_NetworkMessage networkMessage;
- memset(&networkMessage, 0, sizeof(networkMessage));
- UA_StatusCode res =
- generateNetworkMessage(pubSubConnection, wg, dsmStore, dsWriterIds, (UA_Byte) dsmCount,
- &wg->config.messageSettings, &wg->config.transportSettings,
- &networkMessage);
- if(res != UA_STATUSCODE_GOOD)
- return UA_STATUSCODE_BADINTERNALERROR;
- UA_NetworkMessage_calcSizeBinary(&networkMessage, &wg->bufferedMessage);
- /* Allocate the buffer. Allocate on the stack if the buffer is small. */
- UA_ByteString buf;
- size_t msgSize = UA_NetworkMessage_calcSizeBinary(&networkMessage, NULL);
- res = UA_ByteString_allocBuffer(&buf, msgSize);
- if(res != UA_STATUSCODE_GOOD)
- return UA_STATUSCODE_BADOUTOFMEMORY;
- wg->bufferedMessage.buffer = buf;
- const UA_Byte *bufEnd = &wg->bufferedMessage.buffer.data[wg->bufferedMessage.buffer.length];
- UA_Byte *bufPos = wg->bufferedMessage.buffer.data;
- UA_NetworkMessage_encodeBinary(&networkMessage, &bufPos, bufEnd);
- /* Clean up DSM */
- for(size_t i = 0; i < dsmCount; i++){
- UA_free(dsmStore[i].data.keyFrameData.dataSetFields);
-#ifdef UA_ENABLE_JSON_ENCODING
- UA_free(dsmStore[i].data.keyFrameData.fieldNames);
-#endif
- }
- }
- return UA_STATUSCODE_GOOD;
-}
-
-UA_StatusCode
-UA_Server_unfreezeWriterGroupConfiguration(UA_Server *server, const UA_NodeId writerGroup){
- UA_WriterGroup *wg = UA_WriterGroup_findWGbyId(server, writerGroup);
- if(!wg)
- return UA_STATUSCODE_BADNOTFOUND;
- //if(wg->config.rtLevel == UA_PUBSUB_RT_NONE){
- // UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
- // "PubSub configuration freeze without RT configuration has no effect.");
- // return UA_STATUSCODE_BADCONFIGURATIONERROR;
- //}
- //PubSubConnection freezeCounter--
- UA_PubSubConnection *pubSubConnection = wg->linkedConnection;
- pubSubConnection->configurationFreezeCounter--;
- if(pubSubConnection->configurationFreezeCounter == 0){
- pubSubConnection->config->configurationFrozen = UA_FALSE;
- }
- //WriterGroup unfreeze
- wg->config.configurationFrozen = UA_FALSE;
- //DataSetWriter unfreeze
- UA_DataSetWriter *dataSetWriter;
- LIST_FOREACH(dataSetWriter, &wg->writers, listEntry) {
- UA_PublishedDataSet *publishedDataSet =
- UA_PublishedDataSet_findPDSbyId(server, dataSetWriter->connectedDataSet);
- //PublishedDataSet freezeCounter--
- publishedDataSet->configurationFreezeCounter--;
- if(publishedDataSet->configurationFreezeCounter == 0){
- publishedDataSet->config.configurationFrozen = UA_FALSE;
- UA_DataSetField *dataSetField;
- TAILQ_FOREACH(dataSetField, &publishedDataSet->fields, listEntry){
- dataSetField->config.configurationFrozen = UA_FALSE;
- }
- }
- dataSetWriter->config.configurationFrozen = UA_FALSE;
- }
- return UA_STATUSCODE_GOOD;
-}
-
-UA_StatusCode UA_EXPORT
-UA_Server_setWriterGroupOperational(UA_Server *server, const UA_NodeId writerGroup){
- UA_WriterGroup *wg = UA_WriterGroup_findWGbyId(server, writerGroup);
- if(!wg)
- return UA_STATUSCODE_BADNOTFOUND;
- return UA_WriterGroup_setPubSubState(server, UA_PUBSUBSTATE_OPERATIONAL, wg);
-}
-
-UA_StatusCode UA_EXPORT
-UA_Server_setWriterGroupDisabled(UA_Server *server, const UA_NodeId writerGroup){
- UA_WriterGroup *wg = UA_WriterGroup_findWGbyId(server, writerGroup);
- if(!wg)
- return UA_STATUSCODE_BADNOTFOUND;
- return UA_WriterGroup_setPubSubState(server, UA_PUBSUBSTATE_DISABLED, wg);
-}
-
/**********************************************/
/* PublishedDataSet */
/**********************************************/
+
UA_StatusCode
UA_PublishedDataSetConfig_copy(const UA_PublishedDataSetConfig *src,
UA_PublishedDataSetConfig *dst) {
UA_StatusCode res = UA_STATUSCODE_GOOD;
memcpy(dst, src, sizeof(UA_PublishedDataSetConfig));
res |= UA_String_copy(&src->name, &dst->name);
- switch(src->publishedDataSetType){
+ switch(src->publishedDataSetType) {
case UA_PUBSUB_DATASET_PUBLISHEDITEMS:
//no additional items
break;
case UA_PUBSUB_DATASET_PUBLISHEDITEMS_TEMPLATE:
- if(src->config.itemsTemplate.variablesToAddSize > 0){
+ if(src->config.itemsTemplate.variablesToAddSize > 0) {
dst->config.itemsTemplate.variablesToAdd = (UA_PublishedVariableDataType *)
UA_calloc(src->config.itemsTemplate.variablesToAddSize,
sizeof(UA_PublishedVariableDataType));
@@ -28504,7 +28011,7 @@ UA_PublishedDataSetConfig_copy(const UA_PublishedDataSetConfig *src,
src->config.itemsTemplate.variablesToAddSize;
}
- for(size_t i = 0; i < src->config.itemsTemplate.variablesToAddSize; i++){
+ for(size_t i = 0; i < src->config.itemsTemplate.variablesToAddSize; i++) {
res |= UA_PublishedVariableDataType_copy(&src->config.itemsTemplate.variablesToAdd[i],
&dst->config.itemsTemplate.variablesToAdd[i]);
}
@@ -28524,19 +28031,13 @@ UA_PublishedDataSetConfig_copy(const UA_PublishedDataSetConfig *src,
UA_StatusCode
UA_Server_getPublishedDataSetConfig(UA_Server *server, const UA_NodeId pds,
- UA_PublishedDataSetConfig *config){
+ UA_PublishedDataSetConfig *config) {
if(!config)
return UA_STATUSCODE_BADINVALIDARGUMENT;
-
- UA_PublishedDataSet *currentPublishedDataSet = UA_PublishedDataSet_findPDSbyId(server, pds);
- if(!currentPublishedDataSet)
+ UA_PublishedDataSet *currentPDS = UA_PublishedDataSet_findPDSbyId(server, pds);
+ if(!currentPDS)
return UA_STATUSCODE_BADNOTFOUND;
-
- UA_PublishedDataSetConfig tmpPublishedDataSetConfig;
- //deep copy of the actual config
- UA_PublishedDataSetConfig_copy(&currentPublishedDataSet->config, &tmpPublishedDataSetConfig);
- *config = tmpPublishedDataSetConfig;
- return UA_STATUSCODE_GOOD;
+ return UA_PublishedDataSetConfig_copy(&currentPDS->config, config);
}
UA_StatusCode
@@ -28544,17 +28045,15 @@ UA_Server_getPublishedDataSetMetaData(UA_Server *server, const UA_NodeId pds,
UA_DataSetMetaDataType *metaData) {
if(!metaData)
return UA_STATUSCODE_BADINVALIDARGUMENT;
-
- UA_PublishedDataSet *currentPublishedDataSet = UA_PublishedDataSet_findPDSbyId(server, pds);
- if(!currentPublishedDataSet)
+ UA_PublishedDataSet *currentPDS = UA_PublishedDataSet_findPDSbyId(server, pds);
+ if(!currentPDS)
return UA_STATUSCODE_BADNOTFOUND;
-
- return UA_DataSetMetaDataType_copy(&currentPublishedDataSet->dataSetMetaData, metaData);
+ return UA_DataSetMetaDataType_copy(&currentPDS->dataSetMetaData, metaData);
}
UA_PublishedDataSet *
UA_PublishedDataSet_findPDSbyId(UA_Server *server, UA_NodeId identifier) {
- UA_PublishedDataSet *tmpPDS;
+ UA_PublishedDataSet *tmpPDS = NULL;
TAILQ_FOREACH(tmpPDS, &server->pubSubManager.publishedDataSets, listEntry) {
if(UA_NodeId_equal(&tmpPDS->identifier, &identifier))
break;
@@ -28586,259 +28085,312 @@ UA_PublishedDataSetConfig_clear(UA_PublishedDataSetConfig *pdsConfig) {
void
UA_PublishedDataSet_clear(UA_Server *server, UA_PublishedDataSet *publishedDataSet) {
- UA_PublishedDataSetConfig_clear(&publishedDataSet->config);
- //delete PDS
UA_DataSetField *field, *tmpField;
TAILQ_FOREACH_SAFE(field, &publishedDataSet->fields, listEntry, tmpField) {
UA_Server_removeDataSetField(server, field->identifier);
}
+ UA_PublishedDataSetConfig_clear(&publishedDataSet->config);
UA_DataSetMetaDataType_clear(&publishedDataSet->dataSetMetaData);
UA_NodeId_clear(&publishedDataSet->identifier);
}
+/* The fieldMetaData variable has to be cleaned up external in case of an error */
static UA_StatusCode
-generateFieldMetaData(UA_Server *server, UA_DataSetField *field, UA_FieldMetaData *fieldMetaData) {
- switch (field->config.dataSetFieldType){
- case UA_PUBSUB_DATASETFIELD_VARIABLE:
- if(UA_String_copy(&field->config.field.variable.fieldNameAlias, &fieldMetaData->name) != UA_STATUSCODE_GOOD)
- return UA_STATUSCODE_BADINTERNALERROR;
- fieldMetaData->description = UA_LOCALIZEDTEXT_ALLOC("", "");
- fieldMetaData->dataSetFieldId = UA_GUID_NULL;
-
- //ToDo after freeze PR, the value source must be checked (other behavior for static value source)
- if(field->config.field.variable.staticValueSourceEnabled) {
- if (field->config.field.variable.staticValueSource.value.arrayDimensionsSize > 0) {
- fieldMetaData->arrayDimensions = (UA_UInt32 *) UA_calloc(
- field->config.field.variable.staticValueSource.value.arrayDimensionsSize, sizeof(UA_UInt32));
- if(fieldMetaData->arrayDimensions == NULL)
- return UA_STATUSCODE_BADOUTOFMEMORY;
- memcpy(fieldMetaData->arrayDimensions,
- field->config.field.variable.staticValueSource.value.arrayDimensions,
- sizeof(UA_UInt32) *field->config.field.variable.staticValueSource.value.arrayDimensionsSize);
- }
- fieldMetaData->arrayDimensionsSize = field->config.field.variable.staticValueSource.value.arrayDimensionsSize;
- if(UA_NodeId_copy(&field->config.field.variable.staticValueSource.value.type->typeId,
- &fieldMetaData->dataType) != UA_STATUSCODE_GOOD){
- if(fieldMetaData->arrayDimensions){
- UA_free(fieldMetaData->arrayDimensions);
- return UA_STATUSCODE_BADINTERNALERROR;
- }
- }
- fieldMetaData->properties = NULL;
- fieldMetaData->propertiesSize = 0;
- //TODO collect value rank for the static field source
- fieldMetaData->fieldFlags = UA_DATASETFIELDFLAGS_NONE;
- return UA_STATUSCODE_GOOD;
- }
- UA_Variant value;
- UA_Variant_init(&value);
- if(UA_Server_readArrayDimensions(server, field->config.field.variable.publishParameters.publishedVariable,
- &value) != UA_STATUSCODE_GOOD){
- UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
- "PubSub meta data generation. Reading ArrayDimension failed.");
- } else {
- if (value.arrayDimensionsSize > 0) {
- fieldMetaData->arrayDimensions = (UA_UInt32 *) UA_calloc(value.arrayDimensionsSize, sizeof(UA_UInt32));
- if(fieldMetaData->arrayDimensions == NULL)
- return UA_STATUSCODE_BADOUTOFMEMORY;
- memcpy(fieldMetaData->arrayDimensions, value.arrayDimensions, sizeof(UA_UInt32)*value.arrayDimensionsSize);
- }
- fieldMetaData->arrayDimensionsSize = value.arrayDimensionsSize;
- }
- if(UA_Server_readDataType(server, field->config.field.variable.publishParameters.publishedVariable,
- &fieldMetaData->dataType) != UA_STATUSCODE_GOOD){
- if(fieldMetaData->arrayDimensions){
- UA_free(fieldMetaData->arrayDimensions);
- return UA_STATUSCODE_BADINTERNALERROR;
- }
- }
- fieldMetaData->properties = NULL;
- fieldMetaData->propertiesSize = 0;
- UA_Int32 valueRank;
- if(UA_Server_readValueRank(server, field->config.field.variable.publishParameters.publishedVariable,
- &valueRank) != UA_STATUSCODE_GOOD){
- if(fieldMetaData->arrayDimensions){
- UA_free(fieldMetaData->arrayDimensions);
- return UA_STATUSCODE_BADINTERNALERROR;
- }
- }
- fieldMetaData->valueRank = valueRank;
- if(field->config.field.variable.promotedField){
- fieldMetaData->fieldFlags = UA_DATASETFIELDFLAGS_PROMOTEDFIELD;
- } else {
- fieldMetaData->fieldFlags = UA_DATASETFIELDFLAGS_NONE;
- }
- //TODO collect the following fields
- //fieldMetaData.builtInType
- //fieldMetaData.maxStringLength
- return UA_STATUSCODE_GOOD;
- case UA_PUBSUB_DATASETFIELD_EVENT:
- return UA_STATUSCODE_BADNOTSUPPORTED;
- default:
- return UA_STATUSCODE_BADNOTSUPPORTED;
+generateFieldMetaData(UA_Server *server, UA_DataSetField *field,
+ UA_FieldMetaData *fieldMetaData) {
+ if(field->config.dataSetFieldType != UA_PUBSUB_DATASETFIELD_VARIABLE)
+ return UA_STATUSCODE_BADNOTSUPPORTED;
+
+ /* Set the field identifier */
+ fieldMetaData->dataSetFieldId = UA_PubSubManager_generateUniqueGuid(server);
+
+ /* Set the description */
+ fieldMetaData->description = UA_LOCALIZEDTEXT_ALLOC("", "");
+
+ /* Set the name */
+ const UA_DataSetVariableConfig *var = &field->config.field.variable;
+ UA_StatusCode res = UA_String_copy(&var->fieldNameAlias, &fieldMetaData->name);
+ UA_CHECK_STATUS(res, return res);
+
+ /* Static value source. ToDo after freeze PR, the value source must be
+ * checked (other behavior for static value source) */
+ if(var->rtValueSource.rtFieldSourceEnabled &&
+ !var->rtValueSource.rtInformationModelNode) {
+ const UA_DataValue *svs = *var->rtValueSource.staticValueSource;
+ if(svs->value.arrayDimensionsSize > 0) {
+ fieldMetaData->arrayDimensions = (UA_UInt32 *)
+ UA_calloc(svs->value.arrayDimensionsSize, sizeof(UA_UInt32));
+ if(fieldMetaData->arrayDimensions == NULL)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ memcpy(fieldMetaData->arrayDimensions, svs->value.arrayDimensions,
+ sizeof(UA_UInt32) * svs->value.arrayDimensionsSize);
+ }
+ fieldMetaData->arrayDimensionsSize = svs->value.arrayDimensionsSize;
+
+ res = UA_NodeId_copy(&svs->value.type->typeId, &fieldMetaData->dataType);
+ UA_CHECK_STATUS(res, return res);
+
+ //TODO collect value rank for the static field source
+ fieldMetaData->properties = NULL;
+ fieldMetaData->propertiesSize = 0;
+ fieldMetaData->fieldFlags = UA_DATASETFIELDFLAGS_NONE;
+ return UA_STATUSCODE_GOOD;
}
+
+ /* Set the Array Dimensions */
+ const UA_PublishedVariableDataType *pp = &var->publishParameters;
+ UA_Variant value;
+ UA_Variant_init(&value);
+ res = UA_Server_readArrayDimensions(server, pp->publishedVariable, &value);
+ UA_CHECK_STATUS_LOG(res, return res,
+ WARNING, &server->config.logger, UA_LOGCATEGORY_SERVER,
+ "PubSub meta data generation. Reading the array dimensions failed.");
+
+ if(value.arrayDimensionsSize > 0) {
+ fieldMetaData->arrayDimensions = (UA_UInt32 *)
+ UA_calloc(value.arrayDimensionsSize, sizeof(UA_UInt32));
+ if(!fieldMetaData->arrayDimensions)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ memcpy(fieldMetaData->arrayDimensions, value.arrayDimensions,
+ sizeof(UA_UInt32)*value.arrayDimensionsSize);
+ }
+ fieldMetaData->arrayDimensionsSize = value.arrayDimensionsSize;
+
+ /* Set the DataType */
+ res = UA_Server_readDataType(server, pp->publishedVariable,
+ &fieldMetaData->dataType);
+ UA_CHECK_STATUS_LOG(res, return res,
+ WARNING, &server->config.logger, UA_LOGCATEGORY_SERVER,
+ "PubSub meta data generation. Reading the datatype failed.");
+
+ if(!UA_NodeId_isNull(&fieldMetaData->dataType)) {
+ const UA_DataType *currentDataType =
+ UA_findDataTypeWithCustom(&fieldMetaData->dataType,
+ server->config.customDataTypes);
+#ifdef UA_ENABLE_TYPEDESCRIPTION
+ UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "MetaData creation. Found DataType %s.", currentDataType->typeName);
+#endif
+ /* Check if the datatype is a builtInType, if yes set the builtinType.
+ * TODO: Remove the magic number */
+ if(currentDataType->typeKind <= UA_DATATYPEKIND_ENUM)
+ fieldMetaData->builtInType = (UA_Byte)currentDataType->typeKind;
+ } else {
+ UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "PubSub meta data generation. DataType is UA_NODEID_NULL.");
+ }
+
+ /* Set the ValueRank */
+ UA_Int32 valueRank;
+ res = UA_Server_readValueRank(server, pp->publishedVariable, &valueRank);
+ UA_CHECK_STATUS_LOG(res, return res,
+ WARNING, &server->config.logger, UA_LOGCATEGORY_SERVER,
+ "PubSub meta data generation. Reading the value rank failed.");
+ fieldMetaData->valueRank = valueRank;
+
+ /* PromotedField? */
+ if(var->promotedField)
+ fieldMetaData->fieldFlags = UA_DATASETFIELDFLAGS_PROMOTEDFIELD;
+ else
+ fieldMetaData->fieldFlags = UA_DATASETFIELDFLAGS_NONE;
+
+ /* Properties */
+ fieldMetaData->properties = NULL;
+ fieldMetaData->propertiesSize = 0;
+
+ //TODO collect the following fields*/
+ //fieldMetaData.builtInType
+ //fieldMetaData.maxStringLength
+
+ return UA_STATUSCODE_GOOD;
}
UA_DataSetFieldResult
UA_Server_addDataSetField(UA_Server *server, const UA_NodeId publishedDataSet,
const UA_DataSetFieldConfig *fieldConfig,
UA_NodeId *fieldIdentifier) {
- UA_StatusCode retVal = UA_STATUSCODE_GOOD;
- UA_DataSetFieldResult result = {UA_STATUSCODE_BADINVALIDARGUMENT, {0, 0}};
- if(!fieldConfig)
+ UA_DataSetFieldResult result = {0};
+ if(!fieldConfig) {
+ result.result = UA_STATUSCODE_BADINVALIDARGUMENT;
return result;
+ }
- UA_PublishedDataSet *currentDataSet = UA_PublishedDataSet_findPDSbyId(server, publishedDataSet);
- if(currentDataSet == NULL){
+ UA_PublishedDataSet *currDS =
+ UA_PublishedDataSet_findPDSbyId(server, publishedDataSet);
+ if(!currDS) {
result.result = UA_STATUSCODE_BADNOTFOUND;
return result;
}
- if(currentDataSet->config.configurationFrozen){
+ if(currDS->configurationFrozen) {
UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
"Adding DataSetField failed. PublishedDataSet is frozen.");
result.result = UA_STATUSCODE_BADCONFIGURATIONERROR;
return result;
}
- if(currentDataSet->config.publishedDataSetType != UA_PUBSUB_DATASET_PUBLISHEDITEMS){
+ if(currDS->config.publishedDataSetType != UA_PUBSUB_DATASET_PUBLISHEDITEMS) {
result.result = UA_STATUSCODE_BADNOTIMPLEMENTED;
return result;
}
- UA_DataSetField *newField = (UA_DataSetField *) UA_calloc(1, sizeof(UA_DataSetField));
- if(!newField){
+ UA_DataSetField *newField = (UA_DataSetField*)UA_calloc(1, sizeof(UA_DataSetField));
+ if(!newField) {
result.result = UA_STATUSCODE_BADINTERNALERROR;
return result;
}
- UA_DataSetFieldConfig tmpFieldConfig;
- retVal |= UA_DataSetFieldConfig_copy(fieldConfig, &tmpFieldConfig);
- newField->config = tmpFieldConfig;
- UA_PubSubManager_generateUniqueNodeId(server, &newField->identifier);
- if(fieldIdentifier != NULL){
- UA_NodeId_copy(&newField->identifier, fieldIdentifier);
+ UA_StatusCode retVal = UA_DataSetFieldConfig_copy(fieldConfig, &newField->config);
+ if(retVal != UA_STATUSCODE_GOOD) {
+ UA_free(newField);
+ result.result = retVal;
+ return result;
}
- newField->publishedDataSet = currentDataSet->identifier;
- //update major version of parent published data set
- currentDataSet->dataSetMetaData.configurationVersion.majorVersion = UA_PubSubConfigurationVersionTimeDifference();
- /* The order of DataSetFields should be the same in both creating and publishing.
- * So adding DataSetFields at the the end of the DataSets using TAILQ structure */
- if (currentDataSet->fieldSize != 0)
- TAILQ_INSERT_TAIL(&currentDataSet->fields, newField, listEntry);
- else
- TAILQ_INSERT_HEAD(&currentDataSet->fields, newField, listEntry);
- if(newField->config.field.variable.promotedField)
- currentDataSet->promotedFieldsCount++;
- currentDataSet->fieldSize++;
-
- //generate fieldMetadata within the DataSetMetaData
- currentDataSet->dataSetMetaData.fieldsSize++;
- UA_FieldMetaData *fieldMetaData = (UA_FieldMetaData *)
- UA_realloc(currentDataSet->dataSetMetaData.fields, currentDataSet->dataSetMetaData.fieldsSize *
- sizeof(UA_FieldMetaData));
- if(!fieldMetaData){
- result.result = UA_STATUSCODE_BADOUTOFMEMORY;
+ newField->publishedDataSet = currDS->identifier;
+
+ /* Initialize the field metadata. Also generates a FieldId */
+ UA_FieldMetaData fmd;
+ UA_FieldMetaData_init(&fmd);
+ result.result = generateFieldMetaData(server, newField, &fmd);
+ if(result.result != UA_STATUSCODE_GOOD) {
+ UA_FieldMetaData_clear(&fmd);
+ UA_DataSetFieldConfig_clear(&newField->config);
+ UA_free(newField);
return result;
}
- currentDataSet->dataSetMetaData.fields = fieldMetaData;
- UA_FieldMetaData_init(&fieldMetaData[currentDataSet->fieldSize-1]);
- if(generateFieldMetaData(server, newField, &fieldMetaData[currentDataSet->fieldSize-1]) != UA_STATUSCODE_GOOD){
- UA_Server_removeDataSetField(server, newField->identifier);
- result.result = UA_STATUSCODE_BADINTERNALERROR;
+ /* Append to the metadata fields array. Point of last return. */
+ result.result = UA_Array_append((void**)&currDS->dataSetMetaData.fields,
+ &currDS->dataSetMetaData.fieldsSize,
+ &fmd, &UA_TYPES[UA_TYPES_FIELDMETADATA]);
+ if(result.result != UA_STATUSCODE_GOOD) {
+ UA_FieldMetaData_clear(&fmd);
+ UA_DataSetFieldConfig_clear(&newField->config);
+ UA_free(newField);
return result;
}
- UA_DataSetField *dsf;
+
+ /* Copy the identifier from the metadata. Cannot fail with a guid NodeId. */
+ newField->identifier = UA_NODEID_GUID(1, fmd.dataSetFieldId);
+ if(fieldIdentifier)
+ UA_NodeId_copy(&newField->identifier, fieldIdentifier);
+
+ /* Register the field. The order of DataSetFields should be the same in both
+ * creating and publishing. So adding DataSetFields at the the end of the
+ * DataSets using the TAILQ structure. */
+ TAILQ_INSERT_TAIL(&currDS->fields, newField, listEntry);
+ currDS->fieldSize++;
+
+ if(newField->config.field.variable.promotedField)
+ currDS->promotedFieldsCount++;
+
+ /* The values of the metadata are "borrowed" in a mirrored structure in the
+ * pds. Reset them after resizing the array. */
size_t counter = 0;
- TAILQ_FOREACH(dsf, &currentDataSet->fields, listEntry){
- dsf->fieldMetaData = fieldMetaData[counter++];
+ UA_DataSetField *dsf;
+ TAILQ_FOREACH(dsf, &currDS->fields, listEntry) {
+ dsf->fieldMetaData = currDS->dataSetMetaData.fields[counter++];
}
- result.result = retVal;
- result.configurationVersion.majorVersion = currentDataSet->dataSetMetaData.configurationVersion.majorVersion;
- result.configurationVersion.minorVersion = currentDataSet->dataSetMetaData.configurationVersion.minorVersion;
+
+ /* Update major version of parent published data set */
+ currDS->dataSetMetaData.configurationVersion.majorVersion =
+ UA_PubSubConfigurationVersionTimeDifference();
+
+ result.configurationVersion.majorVersion =
+ currDS->dataSetMetaData.configurationVersion.majorVersion;
+ result.configurationVersion.minorVersion =
+ currDS->dataSetMetaData.configurationVersion.minorVersion;
return result;
}
UA_DataSetFieldResult
UA_Server_removeDataSetField(UA_Server *server, const UA_NodeId dsf) {
+ UA_DataSetFieldResult result = {0};
+
UA_DataSetField *currentField = UA_DataSetField_findDSFbyId(server, dsf);
- UA_DataSetFieldResult result = {UA_STATUSCODE_BADNOTFOUND, {0, 0}};
- if(!currentField)
+ if(!currentField) {
+ result.result = UA_STATUSCODE_BADNOTFOUND;
return result;
+ }
- if(currentField->config.configurationFrozen){
+ if(currentField->configurationFrozen) {
UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
"Remove DataSetField failed. DataSetField is frozen.");
result.result = UA_STATUSCODE_BADCONFIGURATIONERROR;
return result;
}
- UA_PublishedDataSet *parentPublishedDataSet =
+ UA_PublishedDataSet *pds =
UA_PublishedDataSet_findPDSbyId(server, currentField->publishedDataSet);
- if(!parentPublishedDataSet)
+ if(!pds) {
+ result.result = UA_STATUSCODE_BADNOTFOUND;
return result;
+ }
- if(parentPublishedDataSet->config.configurationFrozen){
+ if(pds->configurationFrozen) {
UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
"Remove DataSetField failed. PublishedDataSet is frozen.");
result.result = UA_STATUSCODE_BADCONFIGURATIONERROR;
return result;
}
- parentPublishedDataSet->fieldSize--;
+ /* Reduce the counters before the config is cleaned up */
if(currentField->config.field.variable.promotedField)
- parentPublishedDataSet->promotedFieldsCount--;
- /* update major version of PublishedDataSet */
- parentPublishedDataSet->dataSetMetaData.configurationVersion.majorVersion =
+ pds->promotedFieldsCount--;
+ pds->fieldSize--;
+
+ /* Update major version of PublishedDataSet */
+ pds->dataSetMetaData.configurationVersion.majorVersion =
UA_PubSubConfigurationVersionTimeDifference();
+ /* Clean up */
currentField->fieldMetaData.arrayDimensions = NULL;
currentField->fieldMetaData.properties = NULL;
currentField->fieldMetaData.name = UA_STRING_NULL;
currentField->fieldMetaData.description.locale = UA_STRING_NULL;
currentField->fieldMetaData.description.text = UA_STRING_NULL;
UA_DataSetField_clear(currentField);
- TAILQ_REMOVE(&parentPublishedDataSet->fields, currentField, listEntry);
+
+ /* Remove */
+ TAILQ_REMOVE(&pds->fields, currentField, listEntry);
UA_free(currentField);
- result.result = UA_STATUSCODE_GOOD;
- //regenerate DataSetMetaData
- parentPublishedDataSet->dataSetMetaData.fieldsSize--;
- if(parentPublishedDataSet->dataSetMetaData.fieldsSize > 0){
- for(size_t i = 0; i < parentPublishedDataSet->dataSetMetaData.fieldsSize+1; i++) {
- UA_FieldMetaData_clear(&parentPublishedDataSet->dataSetMetaData.fields[i]);
+ /* Regenerate DataSetMetaData */
+ pds->dataSetMetaData.fieldsSize--;
+ if(pds->dataSetMetaData.fieldsSize > 0) {
+ for(size_t i = 0; i < pds->dataSetMetaData.fieldsSize+1; i++) {
+ UA_FieldMetaData_clear(&pds->dataSetMetaData.fields[i]);
}
- UA_free(parentPublishedDataSet->dataSetMetaData.fields);
+ UA_free(pds->dataSetMetaData.fields);
UA_FieldMetaData *fieldMetaData = (UA_FieldMetaData *)
- UA_calloc(parentPublishedDataSet->dataSetMetaData.fieldsSize,
- sizeof(UA_FieldMetaData));
- if(!fieldMetaData){
+ UA_calloc(pds->dataSetMetaData.fieldsSize, sizeof(UA_FieldMetaData));
+ if(!fieldMetaData) {
result.result = UA_STATUSCODE_BADOUTOFMEMORY;
return result;
}
UA_DataSetField *tmpDSF;
size_t counter = 0;
- TAILQ_FOREACH(tmpDSF, &parentPublishedDataSet->fields, listEntry){
- UA_FieldMetaData tmpFieldMetaData;
- UA_FieldMetaData_init(&tmpFieldMetaData);
- if(generateFieldMetaData(server, tmpDSF, &tmpFieldMetaData) != UA_STATUSCODE_GOOD){
+ TAILQ_FOREACH(tmpDSF, &pds->fields, listEntry){
+ result.result = generateFieldMetaData(server, tmpDSF, &fieldMetaData[counter]);
+ if(result.result != UA_STATUSCODE_GOOD) {
+ UA_FieldMetaData_clear(&fieldMetaData[counter]);
UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
"PubSub MetaData generation failed!");
- //TODO how to ensure consistency if the metadata regeneration fails
- result.result = UA_STATUSCODE_BADINTERNALERROR;
+ break;
}
- fieldMetaData[counter++] = tmpFieldMetaData;
+ counter++;
}
- parentPublishedDataSet->dataSetMetaData.fields = fieldMetaData;
+ pds->dataSetMetaData.fields = fieldMetaData;
} else {
- UA_FieldMetaData_delete(parentPublishedDataSet->dataSetMetaData.fields);
- parentPublishedDataSet->dataSetMetaData.fields = NULL;
+ UA_FieldMetaData_delete(pds->dataSetMetaData.fields);
+ pds->dataSetMetaData.fields = NULL;
}
- result.configurationVersion.majorVersion = parentPublishedDataSet->dataSetMetaData.configurationVersion.majorVersion;
- result.configurationVersion.minorVersion = parentPublishedDataSet->dataSetMetaData.configurationVersion.minorVersion;
+ result.configurationVersion.majorVersion =
+ pds->dataSetMetaData.configurationVersion.majorVersion;
+ result.configurationVersion.minorVersion =
+ pds->dataSetMetaData.configurationVersion.minorVersion;
return result;
}
@@ -28854,13 +28406,14 @@ UA_DataSetWriterConfig_copy(const UA_DataSetWriterConfig *src,
retVal |= UA_String_copy(&src->name, &dst->name);
retVal |= UA_String_copy(&src->dataSetName, &dst->dataSetName);
retVal |= UA_ExtensionObject_copy(&src->messageSettings, &dst->messageSettings);
- if (src->dataSetWriterPropertiesSize > 0) {
+ if(src->dataSetWriterPropertiesSize > 0) {
dst->dataSetWriterProperties = (UA_KeyValuePair *)
UA_calloc(src->dataSetWriterPropertiesSize, sizeof(UA_KeyValuePair));
if(!dst->dataSetWriterProperties)
return UA_STATUSCODE_BADOUTOFMEMORY;
for(size_t i = 0; i < src->dataSetWriterPropertiesSize; i++){
- retVal |= UA_KeyValuePair_copy(&src->dataSetWriterProperties[i], &dst->dataSetWriterProperties[i]);
+ retVal |= UA_KeyValuePair_copy(&src->dataSetWriterProperties[i],
+ &dst->dataSetWriterProperties[i]);
}
}
return retVal;
@@ -28868,20 +28421,26 @@ UA_DataSetWriterConfig_copy(const UA_DataSetWriterConfig *src,
UA_StatusCode
UA_Server_getDataSetWriterConfig(UA_Server *server, const UA_NodeId dsw,
- UA_DataSetWriterConfig *config){
- UA_StatusCode retVal = UA_STATUSCODE_GOOD;
+ UA_DataSetWriterConfig *config) {
if(!config)
return UA_STATUSCODE_BADINVALIDARGUMENT;
-
UA_DataSetWriter *currentDataSetWriter = UA_DataSetWriter_findDSWbyId(server, dsw);
if(!currentDataSetWriter)
return UA_STATUSCODE_BADNOTFOUND;
+ return UA_DataSetWriterConfig_copy(&currentDataSetWriter->config, config);
+}
- UA_DataSetWriterConfig tmpWriterConfig;
- //deep copy of the actual config
- retVal |= UA_DataSetWriterConfig_copy(&currentDataSetWriter->config, &tmpWriterConfig);
- *config = tmpWriterConfig;
- return retVal;
+UA_StatusCode
+UA_Server_DataSetWriter_getState(UA_Server *server, UA_NodeId dataSetWriterIdentifier,
+ UA_PubSubState *state) {
+ if((server == NULL) || (state == NULL))
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+ UA_DataSetWriter *currentDataSetWriter =
+ UA_DataSetWriter_findDSWbyId(server, dataSetWriterIdentifier);
+ if(currentDataSetWriter == NULL)
+ return UA_STATUSCODE_BADNOTFOUND;
+ *state = currentDataSetWriter->state;
+ return UA_STATUSCODE_GOOD;
}
UA_DataSetWriter *
@@ -28905,7 +28464,7 @@ void
UA_DataSetWriterConfig_clear(UA_DataSetWriterConfig *pdsConfig) {
UA_String_clear(&pdsConfig->name);
UA_String_clear(&pdsConfig->dataSetName);
- for(size_t i = 0; i < pdsConfig->dataSetWriterPropertiesSize; i++){
+ for(size_t i = 0; i < pdsConfig->dataSetWriterPropertiesSize; i++) {
UA_KeyValuePair_clear(&pdsConfig->dataSetWriterProperties[i]);
}
UA_free(pdsConfig->dataSetWriterProperties);
@@ -28915,12 +28474,12 @@ UA_DataSetWriterConfig_clear(UA_DataSetWriterConfig *pdsConfig) {
static void
UA_DataSetWriter_clear(UA_Server *server, UA_DataSetWriter *dataSetWriter) {
UA_DataSetWriterConfig_clear(&dataSetWriter->config);
- //delete DataSetWriter
UA_NodeId_clear(&dataSetWriter->identifier);
UA_NodeId_clear(&dataSetWriter->linkedWriterGroup);
UA_NodeId_clear(&dataSetWriter->connectedDataSet);
+
+ /* Delete lastSamples store */
#ifdef UA_ENABLE_PUBSUB_DELTAFRAMES
- //delete lastSamples store
for(size_t i = 0; i < dataSetWriter->lastSamplesCount; i++) {
UA_DataValue_clear(&dataSetWriter->lastSamples[i].value);
}
@@ -28932,7 +28491,8 @@ UA_DataSetWriter_clear(UA_Server *server, UA_DataSetWriter *dataSetWriter) {
//state machine methods not part of the open62541 state machine API
UA_StatusCode
-UA_DataSetWriter_setPubSubState(UA_Server *server, UA_PubSubState state, UA_DataSetWriter *dataSetWriter) {
+UA_DataSetWriter_setPubSubState(UA_Server *server, UA_PubSubState state,
+ UA_DataSetWriter *dataSetWriter) {
switch(state){
case UA_PUBSUBSTATE_DISABLED:
switch (dataSetWriter->state){
@@ -28944,7 +28504,6 @@ UA_DataSetWriter_setPubSubState(UA_Server *server, UA_PubSubState state, UA_Data
break;
case UA_PUBSUBSTATE_OPERATIONAL:
dataSetWriter->state = UA_PUBSUBSTATE_DISABLED;
-
break;
case UA_PUBSUBSTATE_ERROR:
break;
@@ -29006,232 +28565,20 @@ UA_DataSetWriter_setPubSubState(UA_Server *server, UA_PubSubState state, UA_Data
return UA_STATUSCODE_GOOD;
}
-/**********************************************/
-/* WriterGroup */
-/**********************************************/
-
-UA_StatusCode
-UA_WriterGroupConfig_copy(const UA_WriterGroupConfig *src,
- UA_WriterGroupConfig *dst){
- UA_StatusCode retVal = UA_STATUSCODE_GOOD;
- memcpy(dst, src, sizeof(UA_WriterGroupConfig));
- retVal |= UA_String_copy(&src->name, &dst->name);
- retVal |= UA_ExtensionObject_copy(&src->transportSettings, &dst->transportSettings);
- retVal |= UA_ExtensionObject_copy(&src->messageSettings, &dst->messageSettings);
- if (src->groupPropertiesSize > 0) {
- dst->groupProperties = (UA_KeyValuePair *) UA_calloc(src->groupPropertiesSize, sizeof(UA_KeyValuePair));
- if(!dst->groupProperties)
- return UA_STATUSCODE_BADOUTOFMEMORY;
- for(size_t i = 0; i < src->groupPropertiesSize; i++){
- retVal |= UA_KeyValuePair_copy(&src->groupProperties[i], &dst->groupProperties[i]);
- }
- }
- return retVal;
-}
-
-UA_StatusCode
-UA_Server_getWriterGroupConfig(UA_Server *server, const UA_NodeId writerGroup,
- UA_WriterGroupConfig *config){
- UA_StatusCode retVal = UA_STATUSCODE_GOOD;
- if(!config)
- return UA_STATUSCODE_BADINVALIDARGUMENT;
-
- UA_WriterGroup *currentWriterGroup = UA_WriterGroup_findWGbyId(server, writerGroup);
- if(!currentWriterGroup){
- return UA_STATUSCODE_BADNOTFOUND;
- }
- UA_WriterGroupConfig tmpWriterGroupConfig;
- //deep copy of the actual config
- retVal |= UA_WriterGroupConfig_copy(&currentWriterGroup->config, &tmpWriterGroupConfig);
- *config = tmpWriterGroupConfig;
- return retVal;
-}
-
-UA_StatusCode
-UA_Server_updateWriterGroupConfig(UA_Server *server, UA_NodeId writerGroupIdentifier,
- const UA_WriterGroupConfig *config){
- if(!config)
- return UA_STATUSCODE_BADINVALIDARGUMENT;
-
- UA_WriterGroup *currentWriterGroup = UA_WriterGroup_findWGbyId(server, writerGroupIdentifier);
- if(!currentWriterGroup)
- return UA_STATUSCODE_BADNOTFOUND;
-
- if(currentWriterGroup->config.configurationFrozen){
- UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
- "Modify WriterGroup failed. WriterGroup is frozen.");
- return UA_STATUSCODE_BADCONFIGURATIONERROR;
- }
-
- //The update functionality will be extended during the next PubSub batches.
- //Currently is only a change of the publishing interval possible.
- if(currentWriterGroup->config.maxEncapsulatedDataSetMessageCount != config->maxEncapsulatedDataSetMessageCount){
- currentWriterGroup->config.maxEncapsulatedDataSetMessageCount = config->maxEncapsulatedDataSetMessageCount;
- if(currentWriterGroup->config.messageSettings.encoding == UA_EXTENSIONOBJECT_ENCODED_NOBODY) {
- UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
- "MaxEncapsulatedDataSetMessag need enabled 'PayloadHeader' within the message settings.");
- }
- }
- if(currentWriterGroup->config.publishingInterval != config->publishingInterval) {
- if(currentWriterGroup->config.rtLevel == UA_PUBSUB_RT_NONE && currentWriterGroup->state == UA_PUBSUBSTATE_OPERATIONAL){
- UA_PubSubManager_removeRepeatedPubSubCallback(server, currentWriterGroup->publishCallbackId);
- currentWriterGroup->config.publishingInterval = config->publishingInterval;
- UA_WriterGroup_addPublishCallback(server, currentWriterGroup);
- } else {
- currentWriterGroup->config.publishingInterval = config->publishingInterval;
- }
- }
- if(currentWriterGroup->config.priority != config->priority) {
- UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
- "No or unsupported WriterGroup update.");
- }
- return UA_STATUSCODE_GOOD;
-}
-
-UA_WriterGroup *
-UA_WriterGroup_findWGbyId(UA_Server *server, UA_NodeId identifier){
- UA_PubSubConnection *tmpConnection;
- TAILQ_FOREACH(tmpConnection, &server->pubSubManager.connections, listEntry){
- UA_WriterGroup *tmpWriterGroup;
- LIST_FOREACH(tmpWriterGroup, &tmpConnection->writerGroups, listEntry) {
- if(UA_NodeId_equal(&identifier, &tmpWriterGroup->identifier)){
- return tmpWriterGroup;
- }
- }
- }
- return NULL;
-}
-
-void
-UA_WriterGroupConfig_clear(UA_WriterGroupConfig *writerGroupConfig){
- //delete writerGroup config
- UA_String_clear(&writerGroupConfig->name);
- UA_ExtensionObject_clear(&writerGroupConfig->transportSettings);
- UA_ExtensionObject_clear(&writerGroupConfig->messageSettings);
- UA_Array_delete(writerGroupConfig->groupProperties,
- writerGroupConfig->groupPropertiesSize,
- &UA_TYPES[UA_TYPES_KEYVALUEPAIR]);
- writerGroupConfig->groupProperties = NULL;
-}
-
-static void
-UA_WriterGroup_clear(UA_Server *server, UA_WriterGroup *writerGroup) {
- UA_WriterGroupConfig_clear(&writerGroup->config);
- //delete WriterGroup
- //delete all writers. Therefore removeDataSetWriter is called from PublishedDataSet
- UA_DataSetWriter *dataSetWriter, *tmpDataSetWriter;
- LIST_FOREACH_SAFE(dataSetWriter, &writerGroup->writers, listEntry, tmpDataSetWriter){
- UA_Server_removeDataSetWriter(server, dataSetWriter->identifier);
- }
- if(writerGroup->bufferedMessage.offsetsSize > 0){
- for (size_t i = 0; i < writerGroup->bufferedMessage.offsetsSize; i++) {
- if(writerGroup->bufferedMessage.offsets[i].contentType == UA_PUBSUB_OFFSETTYPE_PAYLOAD_VARIANT){
- UA_DataValue_delete(writerGroup->bufferedMessage.offsets[i].offsetData.value.value);
- }
- }
- UA_ByteString_deleteMembers(&writerGroup->bufferedMessage.buffer);
- UA_free(writerGroup->bufferedMessage.offsets);
- }
- UA_NodeId_clear(&writerGroup->identifier);
-}
-
-UA_StatusCode
-UA_WriterGroup_setPubSubState(UA_Server *server, UA_PubSubState state, UA_WriterGroup *writerGroup){
- UA_DataSetWriter *dataSetWriter;
- switch(state){
- case UA_PUBSUBSTATE_DISABLED:
- switch (writerGroup->state){
- case UA_PUBSUBSTATE_DISABLED:
- return UA_STATUSCODE_GOOD;
- case UA_PUBSUBSTATE_PAUSED:
- break;
- case UA_PUBSUBSTATE_OPERATIONAL:
- UA_PubSubManager_removeRepeatedPubSubCallback(server, writerGroup->publishCallbackId);
- LIST_FOREACH(dataSetWriter, &writerGroup->writers, listEntry){
- UA_DataSetWriter_setPubSubState(server, UA_PUBSUBSTATE_DISABLED, dataSetWriter);
- }
- writerGroup->state = UA_PUBSUBSTATE_DISABLED;
- break;
- case UA_PUBSUBSTATE_ERROR:
- break;
- default:
- UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
- "Received unknown PubSub state!");
- }
- break;
- case UA_PUBSUBSTATE_PAUSED:
- switch (writerGroup->state){
- case UA_PUBSUBSTATE_DISABLED:
- break;
- case UA_PUBSUBSTATE_PAUSED:
- return UA_STATUSCODE_GOOD;
- case UA_PUBSUBSTATE_OPERATIONAL:
- break;
- case UA_PUBSUBSTATE_ERROR:
- break;
- default:
- UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
- "Received unknown PubSub state!");
- }
- break;
- case UA_PUBSUBSTATE_OPERATIONAL:
- switch (writerGroup->state){
- case UA_PUBSUBSTATE_DISABLED:
- writerGroup->state = UA_PUBSUBSTATE_OPERATIONAL;
- UA_PubSubManager_removeRepeatedPubSubCallback(server, writerGroup->publishCallbackId);
- LIST_FOREACH(dataSetWriter, &writerGroup->writers, listEntry){
- UA_DataSetWriter_setPubSubState(server, UA_PUBSUBSTATE_OPERATIONAL, dataSetWriter);
- }
- UA_WriterGroup_addPublishCallback(server, writerGroup);
- break;
- case UA_PUBSUBSTATE_PAUSED:
- break;
- case UA_PUBSUBSTATE_OPERATIONAL:
- return UA_STATUSCODE_GOOD;
- case UA_PUBSUBSTATE_ERROR:
- break;
- default:
- UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
- "Received unknown PubSub state!");
- }
- break;
- case UA_PUBSUBSTATE_ERROR:
- switch (writerGroup->state){
- case UA_PUBSUBSTATE_DISABLED:
- break;
- case UA_PUBSUBSTATE_PAUSED:
- break;
- case UA_PUBSUBSTATE_OPERATIONAL:
- break;
- case UA_PUBSUBSTATE_ERROR:
- return UA_STATUSCODE_GOOD;
- default:
- UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
- "Received unknown PubSub state!");
- }
- break;
- default:
- UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
- "Received unknown PubSub state!");
- }
- return UA_STATUSCODE_GOOD;
-}
-
-
UA_StatusCode
UA_Server_addDataSetWriter(UA_Server *server,
const UA_NodeId writerGroup, const UA_NodeId dataSet,
const UA_DataSetWriterConfig *dataSetWriterConfig,
UA_NodeId *writerIdentifier) {
- UA_StatusCode retVal = UA_STATUSCODE_GOOD;
if(!dataSetWriterConfig)
return UA_STATUSCODE_BADINVALIDARGUMENT;
- UA_PublishedDataSet *currentDataSetContext = UA_PublishedDataSet_findPDSbyId(server, dataSet);
+ UA_PublishedDataSet *currentDataSetContext =
+ UA_PublishedDataSet_findPDSbyId(server, dataSet);
if(!currentDataSetContext)
return UA_STATUSCODE_BADNOTFOUND;
- if(currentDataSetContext->config.configurationFrozen){
+ if(currentDataSetContext->configurationFrozen){
UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
"Adding DataSetWriter failed. PublishedDataSet is frozen.");
return UA_STATUSCODE_BADCONFIGURATIONERROR;
@@ -29241,16 +28588,17 @@ UA_Server_addDataSetWriter(UA_Server *server,
if(!wg)
return UA_STATUSCODE_BADNOTFOUND;
- if(wg->config.configurationFrozen){
+ if(wg->configurationFrozen) {
UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
"Adding DataSetWriter failed. WriterGroup is frozen.");
return UA_STATUSCODE_BADCONFIGURATIONERROR;
}
- if(wg->config.rtLevel != UA_PUBSUB_RT_NONE){
+ if(wg->config.rtLevel != UA_PUBSUB_RT_NONE) {
UA_DataSetField *tmpDSF;
- TAILQ_FOREACH(tmpDSF, &currentDataSetContext->fields, listEntry){
- if(tmpDSF->config.field.variable.staticValueSourceEnabled != UA_TRUE){
+ TAILQ_FOREACH(tmpDSF, &currentDataSetContext->fields, listEntry) {
+ if(!tmpDSF->config.field.variable.rtValueSource.rtFieldSourceEnabled &&
+ !tmpDSF->config.field.variable.rtValueSource.rtInformationModelNode) {
UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
"Adding DataSetWriter failed. Fields in PDS are not RT capable.");
return UA_STATUSCODE_BADCONFIGURATIONERROR;
@@ -29258,21 +28606,37 @@ UA_Server_addDataSetWriter(UA_Server *server,
}
}
- UA_DataSetWriter *newDataSetWriter = (UA_DataSetWriter *) UA_calloc(1, sizeof(UA_DataSetWriter));
+ UA_DataSetWriter *newDataSetWriter = (UA_DataSetWriter *)
+ UA_calloc(1, sizeof(UA_DataSetWriter));
if(!newDataSetWriter)
return UA_STATUSCODE_BADOUTOFMEMORY;
- //copy the config into the new dataSetWriter
- UA_DataSetWriterConfig tmpDataSetWriterConfig;
- retVal |= UA_DataSetWriterConfig_copy(dataSetWriterConfig, &tmpDataSetWriterConfig);
- newDataSetWriter->config = tmpDataSetWriterConfig;
- //save the current version of the connected PublishedDataSet
- newDataSetWriter->connectedDataSetVersion = currentDataSetContext->dataSetMetaData.configurationVersion;
+ newDataSetWriter->componentType = UA_PUBSUB_COMPONENT_DATASETWRITER;
+
+ UA_StatusCode res = UA_STATUSCODE_GOOD;
+ if(wg->state == UA_PUBSUBSTATE_OPERATIONAL) {
+ res = UA_DataSetWriter_setPubSubState(server, UA_PUBSUBSTATE_OPERATIONAL,
+ newDataSetWriter);
+ if(res != UA_STATUSCODE_GOOD) {
+ UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Add DataSetWriter failed. setPubSubState failed.");
+ UA_free(newDataSetWriter);
+ return res;
+ }
+ }
+
+ /* Copy the config into the new dataSetWriter */
+ res = UA_DataSetWriterConfig_copy(dataSetWriterConfig, &newDataSetWriter->config);
+ UA_CHECK_STATUS(res, UA_free(newDataSetWriter); return res);
+
+ /* Save the current version of the connected PublishedDataSet */
+ newDataSetWriter->connectedDataSetVersion =
+ currentDataSetContext->dataSetMetaData.configurationVersion;
#ifdef UA_ENABLE_PUBSUB_DELTAFRAMES
- //initialize the queue for the last values
- if (currentDataSetContext->fieldSize > 0) {
- newDataSetWriter->lastSamples = (UA_DataSetWriterSample * )
+ /* Initialize the queue for the last values */
+ if(currentDataSetContext->fieldSize > 0) {
+ newDataSetWriter->lastSamples = (UA_DataSetWriterSample*)
UA_calloc(currentDataSetContext->fieldSize, sizeof(UA_DataSetWriterSample));
if(!newDataSetWriter->lastSamples) {
UA_DataSetWriterConfig_clear(&newDataSetWriter->config);
@@ -29287,28 +28651,55 @@ UA_Server_addDataSetWriter(UA_Server *server,
}
#endif
- //connect PublishedDataSet with DataSetWriter
+ /* Connect PublishedDataSet with DataSetWriter */
newDataSetWriter->connectedDataSet = currentDataSetContext->identifier;
newDataSetWriter->linkedWriterGroup = wg->identifier;
- UA_PubSubManager_generateUniqueNodeId(server, &newDataSetWriter->identifier);
- if(writerIdentifier != NULL)
- UA_NodeId_copy(&newDataSetWriter->identifier, writerIdentifier);
- //add the new writer to the group
+
+ /* Add the new writer to the group */
LIST_INSERT_HEAD(&wg->writers, newDataSetWriter, listEntry);
wg->writersCount++;
+
#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL
- addDataSetWriterRepresentation(server, newDataSetWriter);
+ res |= addDataSetWriterRepresentation(server, newDataSetWriter);
+#else
+ UA_PubSubManager_generateUniqueNodeId(&server->pubSubManager,
+ &newDataSetWriter->identifier);
#endif
- return retVal;
+ if(writerIdentifier)
+ UA_NodeId_copy(&newDataSetWriter->identifier, writerIdentifier);
+ return res;
}
UA_StatusCode
-UA_Server_removeDataSetWriter(UA_Server *server, const UA_NodeId dsw){
+UA_DataSetWriter_remove(UA_Server *server, UA_WriterGroup *linkedWriterGroup,
+ UA_DataSetWriter *dataSetWriter) {
+ /* Frozen? */
+ if(linkedWriterGroup->configurationFrozen) {
+ UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Remove DataSetWriter failed. WriterGroup is frozen.");
+ return UA_STATUSCODE_BADCONFIGURATIONERROR;
+ }
+
+ /* Remove from information model */
+#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL
+ removeDataSetWriterRepresentation(server, dataSetWriter);
+#endif
+
+ /* Remove DataSetWriter from group */
+ UA_DataSetWriter_clear(server, dataSetWriter);
+ LIST_REMOVE(dataSetWriter, listEntry);
+ linkedWriterGroup->writersCount--;
+ UA_free(dataSetWriter);
+ return UA_STATUSCODE_GOOD;
+}
+
+UA_StatusCode
+UA_Server_removeDataSetWriter(UA_Server *server, const UA_NodeId dsw) {
UA_DataSetWriter *dataSetWriter = UA_DataSetWriter_findDSWbyId(server, dsw);
if(!dataSetWriter)
return UA_STATUSCODE_BADNOTFOUND;
- if(dataSetWriter->config.configurationFrozen){
+ if(dataSetWriter->configurationFrozen) {
UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
"Remove DataSetWriter failed. DataSetWriter is frozen.");
return UA_STATUSCODE_BADCONFIGURATIONERROR;
@@ -29319,164 +28710,152 @@ UA_Server_removeDataSetWriter(UA_Server *server, const UA_NodeId dsw){
if(!linkedWriterGroup)
return UA_STATUSCODE_BADNOTFOUND;
- if(linkedWriterGroup->config.configurationFrozen){
- UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
- "Remove DataSetWriter failed. WriterGroup is frozen.");
- return UA_STATUSCODE_BADCONFIGURATIONERROR;
- }
-
- UA_PublishedDataSet *publishedDataSet =
- UA_PublishedDataSet_findPDSbyId(server, dataSetWriter->connectedDataSet);
- if(!publishedDataSet)
- return UA_STATUSCODE_BADNOTFOUND;
-
- linkedWriterGroup->writersCount--;
-#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL
- removeDataSetWriterRepresentation(server, dataSetWriter);
-#endif
-
- //remove DataSetWriter from group
- UA_DataSetWriter_clear(server, dataSetWriter);
- LIST_REMOVE(dataSetWriter, listEntry);
- UA_free(dataSetWriter);
- return UA_STATUSCODE_GOOD;
+ return UA_DataSetWriter_remove(server, linkedWriterGroup, dataSetWriter);
}
/**********************************************/
/* DataSetField */
/**********************************************/
+static void
+UA_DataSetField_clear(UA_DataSetField *field) {
+ UA_DataSetFieldConfig_clear(&field->config);
+ UA_NodeId_clear(&field->identifier);
+ UA_NodeId_clear(&field->publishedDataSet);
+ UA_FieldMetaData_clear(&field->fieldMetaData);
+}
+
UA_StatusCode
-UA_DataSetFieldConfig_copy(const UA_DataSetFieldConfig *src, UA_DataSetFieldConfig *dst){
- memcpy(dst, src, sizeof(UA_DataSetFieldConfig));
- if(src->dataSetFieldType == UA_PUBSUB_DATASETFIELD_VARIABLE) {
- UA_String_copy(&src->field.variable.fieldNameAlias, &dst->field.variable.fieldNameAlias);
- UA_PublishedVariableDataType_copy(&src->field.variable.publishParameters,
- &dst->field.variable.publishParameters);
- } else {
+UA_DataSetFieldConfig_copy(const UA_DataSetFieldConfig *src,
+ UA_DataSetFieldConfig *dst) {
+ if(src->dataSetFieldType != UA_PUBSUB_DATASETFIELD_VARIABLE)
return UA_STATUSCODE_BADNOTSUPPORTED;
- }
-
- return UA_STATUSCODE_GOOD;
+ memcpy(dst, src, sizeof(UA_DataSetFieldConfig));
+ UA_StatusCode res = UA_STATUSCODE_GOOD;
+ res |= UA_String_copy(&src->field.variable.fieldNameAlias,
+ &dst->field.variable.fieldNameAlias);
+ res |= UA_PublishedVariableDataType_copy(&src->field.variable.publishParameters,
+ &dst->field.variable.publishParameters);
+ if(res != UA_STATUSCODE_GOOD)
+ UA_DataSetFieldConfig_clear(dst);
+ return res;
}
UA_StatusCode
UA_Server_getDataSetFieldConfig(UA_Server *server, const UA_NodeId dsf,
UA_DataSetFieldConfig *config) {
- UA_StatusCode retVal = UA_STATUSCODE_GOOD;
if(!config)
return UA_STATUSCODE_BADINVALIDARGUMENT;
UA_DataSetField *currentDataSetField = UA_DataSetField_findDSFbyId(server, dsf);
if(!currentDataSetField)
return UA_STATUSCODE_BADNOTFOUND;
- UA_DataSetFieldConfig tmpFieldConfig;
- //deep copy of the actual config
- retVal |= UA_DataSetFieldConfig_copy(&currentDataSetField->config, &tmpFieldConfig);
- *config = tmpFieldConfig;
- return retVal;
+ return UA_DataSetFieldConfig_copy(&currentDataSetField->config, config);
}
UA_DataSetField *
UA_DataSetField_findDSFbyId(UA_Server *server, UA_NodeId identifier) {
UA_PublishedDataSet *tmpPDS;
- TAILQ_FOREACH(tmpPDS, &server->pubSubManager.publishedDataSets, listEntry){
+ TAILQ_FOREACH(tmpPDS, &server->pubSubManager.publishedDataSets, listEntry) {
UA_DataSetField *tmpField;
- TAILQ_FOREACH(tmpField, &tmpPDS->fields, listEntry){
- if(UA_NodeId_equal(&tmpField->identifier, &identifier)){
+ TAILQ_FOREACH(tmpField, &tmpPDS->fields, listEntry) {
+ if(UA_NodeId_equal(&tmpField->identifier, &identifier))
return tmpField;
- }
}
}
return NULL;
}
void
-UA_DataSetFieldConfig_clear(UA_DataSetFieldConfig *dataSetFieldConfig){
- if(dataSetFieldConfig->dataSetFieldType == UA_PUBSUB_DATASETFIELD_VARIABLE){
+UA_DataSetFieldConfig_clear(UA_DataSetFieldConfig *dataSetFieldConfig) {
+ if(dataSetFieldConfig->dataSetFieldType == UA_PUBSUB_DATASETFIELD_VARIABLE) {
UA_String_clear(&dataSetFieldConfig->field.variable.fieldNameAlias);
UA_PublishedVariableDataType_clear(&dataSetFieldConfig->field.variable.publishParameters);
}
}
-static void
-UA_DataSetField_clear(UA_DataSetField *field) {
- UA_DataSetFieldConfig_clear(&field->config);
- //delete DataSetField
- UA_NodeId_clear(&field->identifier);
- UA_NodeId_clear(&field->publishedDataSet);
- UA_FieldMetaData_clear(&field->fieldMetaData);
-}
-
/*********************************************************/
/* PublishValues handling */
/*********************************************************/
-/**
- * Compare two variants. Internally used for value change detection.
- *
- * @return true if the value has changed
- */
+/* Compare two variants. Internally used for value change detection. */
#ifdef UA_ENABLE_PUBSUB_DELTAFRAMES
static UA_Boolean
-valueChangedVariant(UA_Variant *oldValue, UA_Variant *newValue){
- if(! (oldValue && newValue))
+valueChangedVariant(UA_Variant *oldValue, UA_Variant *newValue) {
+ if(!oldValue || !newValue)
return false;
- UA_ByteString *oldValueEncoding = UA_ByteString_new(), *newValueEncoding = UA_ByteString_new();
- size_t oldValueEncodingSize, newValueEncodingSize;
- oldValueEncodingSize = UA_calcSizeBinary(oldValue, &UA_TYPES[UA_TYPES_VARIANT]);
- newValueEncodingSize = UA_calcSizeBinary(newValue, &UA_TYPES[UA_TYPES_VARIANT]);
- if((oldValueEncodingSize == 0) || (newValueEncodingSize == 0))
+ size_t oldValueEncodingSize = UA_calcSizeBinary(oldValue, &UA_TYPES[UA_TYPES_VARIANT]);
+ size_t newValueEncodingSize = UA_calcSizeBinary(newValue, &UA_TYPES[UA_TYPES_VARIANT]);
+ if(oldValueEncodingSize == 0 || newValueEncodingSize == 0)
return false;
if(oldValueEncodingSize != newValueEncodingSize)
return true;
- if(UA_ByteString_allocBuffer(oldValueEncoding, oldValueEncodingSize) != UA_STATUSCODE_GOOD)
- return false;
-
- if(UA_ByteString_allocBuffer(newValueEncoding, newValueEncodingSize) != UA_STATUSCODE_GOOD)
+ UA_ByteString oldValueEncoding = {0};
+ UA_StatusCode res = UA_ByteString_allocBuffer(&oldValueEncoding, oldValueEncodingSize);
+ if(res != UA_STATUSCODE_GOOD)
return false;
- UA_Byte *bufPosOldValue = oldValueEncoding->data;
- const UA_Byte *bufEndOldValue = &oldValueEncoding->data[oldValueEncoding->length];
- UA_Byte *bufPosNewValue = newValueEncoding->data;
- const UA_Byte *bufEndNewValue = &newValueEncoding->data[newValueEncoding->length];
- if(UA_encodeBinary(oldValue, &UA_TYPES[UA_TYPES_VARIANT],
- &bufPosOldValue, &bufEndOldValue, NULL, NULL) != UA_STATUSCODE_GOOD){
- return false;
- }
- if(UA_encodeBinary(newValue, &UA_TYPES[UA_TYPES_VARIANT],
- &bufPosNewValue, &bufEndNewValue, NULL, NULL) != UA_STATUSCODE_GOOD){
+ UA_ByteString newValueEncoding = {0};
+ res = UA_ByteString_allocBuffer(&newValueEncoding, newValueEncodingSize);
+ if(res != UA_STATUSCODE_GOOD) {
+ UA_ByteString_clear(&oldValueEncoding);
return false;
}
- oldValueEncoding->length = (uintptr_t)bufPosOldValue - (uintptr_t)oldValueEncoding->data;
- newValueEncoding->length = (uintptr_t)bufPosNewValue - (uintptr_t)newValueEncoding->data;
- UA_Boolean compareResult = !UA_ByteString_equal(oldValueEncoding, newValueEncoding);
- UA_ByteString_delete(oldValueEncoding);
- UA_ByteString_delete(newValueEncoding);
+
+ UA_Byte *bufPosOldValue = oldValueEncoding.data;
+ const UA_Byte *bufEndOldValue = &oldValueEncoding.data[oldValueEncoding.length];
+ UA_Byte *bufPosNewValue = newValueEncoding.data;
+ const UA_Byte *bufEndNewValue = &newValueEncoding.data[newValueEncoding.length];
+
+ UA_Boolean compareResult = false; /* default */
+
+ res = UA_encodeBinaryInternal(oldValue, &UA_TYPES[UA_TYPES_VARIANT],
+ &bufPosOldValue, &bufEndOldValue, NULL, NULL);
+ if(res != UA_STATUSCODE_GOOD)
+ goto cleanup;
+
+ res = UA_encodeBinaryInternal(newValue, &UA_TYPES[UA_TYPES_VARIANT],
+ &bufPosNewValue, &bufEndNewValue, NULL, NULL);
+ if(res != UA_STATUSCODE_GOOD)
+ goto cleanup;
+
+ oldValueEncoding.length = (uintptr_t)bufPosOldValue - (uintptr_t)oldValueEncoding.data;
+ newValueEncoding.length = (uintptr_t)bufPosNewValue - (uintptr_t)newValueEncoding.data;
+ compareResult = !UA_ByteString_equal(&oldValueEncoding, &newValueEncoding);
+
+ cleanup:
+ UA_ByteString_clear(&oldValueEncoding);
+ UA_ByteString_clear(&newValueEncoding);
return compareResult;
}
#endif
-/**
- * Obtain the latest value for a specific DataSetField. This method is currently
- * called inside the DataSetMessage generation process.
- */
+/* Obtain the latest value for a specific DataSetField. This method is currently
+ * called inside the DataSetMessage generation process. */
static void
UA_PubSubDataSetField_sampleValue(UA_Server *server, UA_DataSetField *field,
UA_DataValue *value) {
+ UA_PublishedVariableDataType *params = &field->config.field.variable.publishParameters;
+
/* Read the value */
- if(field->config.field.variable.staticValueSourceEnabled == UA_FALSE){
+ if(field->config.field.variable.rtValueSource.rtInformationModelNode) {
+ const UA_VariableNode *rtNode = (const UA_VariableNode *)
+ UA_NODESTORE_GET(server, &params->publishedVariable);
+ *value = **rtNode->valueBackend.backend.external.value;
+ value->value.storageType = UA_VARIANT_DATA_NODELETE;
+ UA_NODESTORE_RELEASE(server, (const UA_Node *) rtNode);
+ } else if(field->config.field.variable.rtValueSource.rtFieldSourceEnabled == UA_FALSE){
UA_ReadValueId rvid;
UA_ReadValueId_init(&rvid);
- rvid.nodeId = field->config.field.variable.publishParameters.publishedVariable;
- rvid.attributeId = field->config.field.variable.publishParameters.attributeId;
- rvid.indexRange = field->config.field.variable.publishParameters.indexRange;
+ rvid.nodeId = params->publishedVariable;
+ rvid.attributeId = params->attributeId;
+ rvid.indexRange = params->indexRange;
*value = UA_Server_read(server, &rvid, UA_TIMESTAMPSTORETURN_BOTH);
} else {
+ *value = **field->config.field.variable.rtValueSource.staticValueSource;
value->value.storageType = UA_VARIANT_DATA_NODELETE;
- *value = field->config.field.variable.staticValueSource;
}
}
@@ -29502,7 +28881,7 @@ UA_PubSubDataSetWriter_generateKeyFrameMessage(UA_Server *server,
dataSetMessage->data.keyFrameData.fieldNames = (UA_String *)
UA_Array_new(currentDataSet->fieldSize, &UA_TYPES[UA_TYPES_STRING]);
if(!dataSetMessage->data.keyFrameData.fieldNames) {
- UA_DataSetMessage_free(dataSetMessage);
+ UA_DataSetMessage_clear(dataSetMessage);
return UA_STATUSCODE_BADOUTOFMEMORY;
}
#endif
@@ -29577,17 +28956,18 @@ UA_PubSubDataSetWriter_generateDeltaFrameMessage(UA_Server *server,
UA_PubSubDataSetField_sampleValue(server, dsf, &value);
/* Check if the value has changed */
- if(valueChangedVariant(&dataSetWriter->lastSamples[counter].value.value, &value.value)) {
+ UA_DataSetWriterSample *ls = &dataSetWriter->lastSamples[counter];
+ if(valueChangedVariant(&ls->value.value, &value.value)) {
/* increase fieldCount for current delta message */
dataSetMessage->data.deltaFrameData.fieldCount++;
- dataSetWriter->lastSamples[counter].valueChanged = true;
+ ls->valueChanged = true;
/* Update last stored sample */
- UA_DataValue_clear(&dataSetWriter->lastSamples[counter].value);
- dataSetWriter->lastSamples[counter].value = value;
+ UA_DataValue_clear(&ls->value);
+ ls->value = value;
} else {
UA_DataValue_clear(&value);
- dataSetWriter->lastSamples[counter].valueChanged = false;
+ ls->valueChanged = false;
}
counter++;
@@ -29637,14 +29017,10 @@ UA_PubSubDataSetWriter_generateDeltaFrameMessage(UA_Server *server,
}
#endif
-/**
- * Generate a DataSetMessage for the given writer.
- *
- * @param dataSetWriter ptr to corresponding writer
- * @return ptr to generated DataSetMessage
- */
-static UA_StatusCode
-UA_DataSetWriter_generateDataSetMessage(UA_Server *server, UA_DataSetMessage *dataSetMessage,
+/* Generate a DataSetMessage for the given writer. */
+UA_StatusCode
+UA_DataSetWriter_generateDataSetMessage(UA_Server *server,
+ UA_DataSetMessage *dataSetMessage,
UA_DataSetWriter *dataSetWriter) {
UA_PublishedDataSet *currentDataSet =
UA_PublishedDataSet_findPDSbyId(server, dataSetWriter->connectedDataSet);
@@ -29654,57 +29030,32 @@ UA_DataSetWriter_generateDataSetMessage(UA_Server *server, UA_DataSetMessage *da
/* Reset the message */
memset(dataSetMessage, 0, sizeof(UA_DataSetMessage));
- /* store messageType to switch between json or uadp (default) */
- UA_UInt16 messageType = UA_TYPES_UADPDATASETWRITERMESSAGEDATATYPE;
- UA_JsonDataSetWriterMessageDataType *jsonDataSetWriterMessageDataType = NULL;
-
/* The configuration Flags are included
* inside the std. defined UA_UadpDataSetWriterMessageDataType */
UA_UadpDataSetWriterMessageDataType defaultUadpConfiguration;
- UA_UadpDataSetWriterMessageDataType *dataSetWriterMessageDataType = NULL;
- if((dataSetWriter->config.messageSettings.encoding == UA_EXTENSIONOBJECT_DECODED ||
- dataSetWriter->config.messageSettings.encoding == UA_EXTENSIONOBJECT_DECODED_NODELETE) &&
- (dataSetWriter->config.messageSettings.content.decoded.type ==
- &UA_TYPES[UA_TYPES_UADPDATASETWRITERMESSAGEDATATYPE])) {
- dataSetWriterMessageDataType = (UA_UadpDataSetWriterMessageDataType *)
- dataSetWriter->config.messageSettings.content.decoded.data;
-
- /* type is UADP */
- messageType = UA_TYPES_UADPDATASETWRITERMESSAGEDATATYPE;
- } else if((dataSetWriter->config.messageSettings.encoding == UA_EXTENSIONOBJECT_DECODED ||
- dataSetWriter->config.messageSettings.encoding == UA_EXTENSIONOBJECT_DECODED_NODELETE) &&
- (dataSetWriter->config.messageSettings.content.decoded.type ==
- &UA_TYPES[UA_TYPES_JSONDATASETWRITERMESSAGEDATATYPE])) {
- jsonDataSetWriterMessageDataType = (UA_JsonDataSetWriterMessageDataType *)
- dataSetWriter->config.messageSettings.content.decoded.data;
-
- /* type is JSON */
- messageType = UA_TYPES_JSONDATASETWRITERMESSAGEDATATYPE;
+ UA_UadpDataSetWriterMessageDataType *dsm = NULL;
+ UA_JsonDataSetWriterMessageDataType *jsonDsm = NULL;
+ const UA_ExtensionObject *ms = &dataSetWriter->config.messageSettings;
+ if((ms->encoding == UA_EXTENSIONOBJECT_DECODED ||
+ ms->encoding == UA_EXTENSIONOBJECT_DECODED_NODELETE) &&
+ ms->content.decoded.type == &UA_TYPES[UA_TYPES_UADPDATASETWRITERMESSAGEDATATYPE]) {
+ dsm = (UA_UadpDataSetWriterMessageDataType*)ms->content.decoded.data; /* type is UADP */
+ } else if((ms->encoding == UA_EXTENSIONOBJECT_DECODED ||
+ ms->encoding == UA_EXTENSIONOBJECT_DECODED_NODELETE) &&
+ ms->content.decoded.type == &UA_TYPES[UA_TYPES_JSONDATASETWRITERMESSAGEDATATYPE]) {
+ jsonDsm = (UA_JsonDataSetWriterMessageDataType*)ms->content.decoded.data; /* type is JSON */
} else {
- /* create default flag configuration if no
+ /* Create default flag configuration if no
* UadpDataSetWriterMessageDataType was passed in */
memset(&defaultUadpConfiguration, 0, sizeof(UA_UadpDataSetWriterMessageDataType));
defaultUadpConfiguration.dataSetMessageContentMask = (UA_UadpDataSetMessageContentMask)
((u64)UA_UADPDATASETMESSAGECONTENTMASK_TIMESTAMP |
(u64)UA_UADPDATASETMESSAGECONTENTMASK_MAJORVERSION |
(u64)UA_UADPDATASETMESSAGECONTENTMASK_MINORVERSION);
- dataSetWriterMessageDataType = &defaultUadpConfiguration;
- }
-
- /* Sanity-test the configuration */
- if(dataSetWriterMessageDataType &&
- (dataSetWriterMessageDataType->networkMessageNumber != 0 ||
- dataSetWriterMessageDataType->dataSetOffset != 0 ||
- dataSetWriterMessageDataType->configuredSize != 0)) {
- UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
- "Static DSM configuration not supported. Using defaults");
- dataSetWriterMessageDataType->networkMessageNumber = 0;
- dataSetWriterMessageDataType->dataSetOffset = 0;
- dataSetWriterMessageDataType->configuredSize = 0;
+ dsm = &defaultUadpConfiguration; /* type is UADP */
}
- /* The field encoding depends on the flags inside the writer config.
- * TODO: This can be moved to the encoding layer. */
+ /* The field encoding depends on the flags inside the writer config. */
if(dataSetWriter->config.dataSetFieldContentMask &
(u64)UA_DATASETFIELDCONTENTMASK_RAWDATA) {
dataSetMessage->header.fieldEncoding = UA_FIELDENCODING_RAWDATA;
@@ -29718,84 +29069,97 @@ UA_DataSetWriter_generateDataSetMessage(UA_Server *server, UA_DataSetMessage *da
dataSetMessage->header.fieldEncoding = UA_FIELDENCODING_VARIANT;
}
- if(messageType == UA_TYPES_UADPDATASETWRITERMESSAGEDATATYPE) {
+ if(dsm) {
+ /* Sanity-test the configuration */
+ if(dsm->networkMessageNumber != 0 ||
+ dsm->dataSetOffset != 0 ||
+ dsm->configuredSize != 0) {
+ UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Static DSM configuration not supported. Using defaults");
+ dsm->networkMessageNumber = 0;
+ dsm->dataSetOffset = 0;
+ dsm->configuredSize = 0;
+ }
+
/* Std: 'The DataSetMessageContentMask defines the flags for the content
* of the DataSetMessage header.' */
- if((u64)dataSetWriterMessageDataType->dataSetMessageContentMask &
+ if((u64)dsm->dataSetMessageContentMask &
(u64)UA_UADPDATASETMESSAGECONTENTMASK_MAJORVERSION) {
dataSetMessage->header.configVersionMajorVersionEnabled = true;
dataSetMessage->header.configVersionMajorVersion =
currentDataSet->dataSetMetaData.configurationVersion.majorVersion;
}
- if((u64)dataSetWriterMessageDataType->dataSetMessageContentMask &
+ if((u64)dsm->dataSetMessageContentMask &
(u64)UA_UADPDATASETMESSAGECONTENTMASK_MINORVERSION) {
dataSetMessage->header.configVersionMinorVersionEnabled = true;
dataSetMessage->header.configVersionMinorVersion =
currentDataSet->dataSetMetaData.configurationVersion.minorVersion;
}
- if((u64)dataSetWriterMessageDataType->dataSetMessageContentMask &
+ if((u64)dsm->dataSetMessageContentMask &
(u64)UA_UADPDATASETMESSAGECONTENTMASK_SEQUENCENUMBER) {
dataSetMessage->header.dataSetMessageSequenceNrEnabled = true;
dataSetMessage->header.dataSetMessageSequenceNr =
dataSetWriter->actualDataSetMessageSequenceCount;
}
- if((u64)dataSetWriterMessageDataType->dataSetMessageContentMask &
+ if((u64)dsm->dataSetMessageContentMask &
(u64)UA_UADPDATASETMESSAGECONTENTMASK_TIMESTAMP) {
dataSetMessage->header.timestampEnabled = true;
dataSetMessage->header.timestamp = UA_DateTime_now();
}
+
/* TODO: Picoseconds resolution not supported atm */
- if((u64)dataSetWriterMessageDataType->dataSetMessageContentMask &
+ if((u64)dsm->dataSetMessageContentMask &
(u64)UA_UADPDATASETMESSAGECONTENTMASK_PICOSECONDS) {
dataSetMessage->header.picoSecondsIncluded = false;
}
/* TODO: Statuscode not supported yet */
- if((u64)dataSetWriterMessageDataType->dataSetMessageContentMask &
+ if((u64)dsm->dataSetMessageContentMask &
(u64)UA_UADPDATASETMESSAGECONTENTMASK_STATUS) {
- dataSetMessage->header.statusEnabled = false;
+ dataSetMessage->header.statusEnabled = true;
}
- } else if(messageType == UA_TYPES_JSONDATASETWRITERMESSAGEDATATYPE) {
- if((u64)jsonDataSetWriterMessageDataType->dataSetMessageContentMask &
+ } else if(jsonDsm) {
+ if((u64)jsonDsm->dataSetMessageContentMask &
(u64)UA_JSONDATASETMESSAGECONTENTMASK_METADATAVERSION) {
dataSetMessage->header.configVersionMajorVersionEnabled = true;
dataSetMessage->header.configVersionMajorVersion =
currentDataSet->dataSetMetaData.configurationVersion.majorVersion;
}
- if((u64)jsonDataSetWriterMessageDataType->dataSetMessageContentMask &
+ if((u64)jsonDsm->dataSetMessageContentMask &
(u64)UA_JSONDATASETMESSAGECONTENTMASK_METADATAVERSION) {
dataSetMessage->header.configVersionMinorVersionEnabled = true;
dataSetMessage->header.configVersionMinorVersion =
currentDataSet->dataSetMetaData.configurationVersion.minorVersion;
}
- if((u64)jsonDataSetWriterMessageDataType->dataSetMessageContentMask &
+ if((u64)jsonDsm->dataSetMessageContentMask &
(u64)UA_JSONDATASETMESSAGECONTENTMASK_SEQUENCENUMBER) {
dataSetMessage->header.dataSetMessageSequenceNrEnabled = true;
dataSetMessage->header.dataSetMessageSequenceNr =
dataSetWriter->actualDataSetMessageSequenceCount;
}
- if((u64)jsonDataSetWriterMessageDataType->dataSetMessageContentMask &
+ if((u64)jsonDsm->dataSetMessageContentMask &
(u64)UA_JSONDATASETMESSAGECONTENTMASK_TIMESTAMP) {
dataSetMessage->header.timestampEnabled = true;
dataSetMessage->header.timestamp = UA_DateTime_now();
}
/* TODO: Statuscode not supported yet */
- if((u64)jsonDataSetWriterMessageDataType->dataSetMessageContentMask &
+ if((u64)jsonDsm->dataSetMessageContentMask &
(u64)UA_JSONDATASETMESSAGECONTENTMASK_STATUS) {
- dataSetMessage->header.statusEnabled = false;
+ dataSetMessage->header.statusEnabled = true;
}
}
/* Set the sequence count. Automatically rolls over to zero */
dataSetWriter->actualDataSetMessageSequenceCount++;
- /* JSON does not differ between deltaframes and keyframes, only keyframes are currently used. */
- if(messageType != UA_TYPES_JSONDATASETWRITERMESSAGEDATATYPE){
+ /* JSON does not differ between deltaframes and keyframes, only keyframes
+ * are currently used. */
+ if(dsm) {
#ifdef UA_ENABLE_PUBSUB_DELTAFRAMES
/* Check if the PublishedDataSet version has changed -> if yes flush the
* lastValue store and send a KeyFrame */
@@ -29807,7 +29171,7 @@ UA_DataSetWriter_generateDataSetMessage(UA_Server *server, UA_DataSetMessage *da
for(size_t i = 0; i < dataSetWriter->lastSamplesCount; i++)
UA_DataValue_clear(&dataSetWriter->lastSamples[i].value);
- /* Realloc pds dependent memory */
+ /* Realloc PDS dependent memory */
dataSetWriter->lastSamplesCount = currentDataSet->fieldSize;
UA_DataSetWriterSample *newSamplesArray = (UA_DataSetWriterSample * )
UA_realloc(dataSetWriter->lastSamples,
@@ -29818,8 +29182,10 @@ UA_DataSetWriter_generateDataSetMessage(UA_Server *server, UA_DataSetMessage *da
memset(dataSetWriter->lastSamples, 0,
sizeof(UA_DataSetWriterSample) * dataSetWriter->lastSamplesCount);
- dataSetWriter->connectedDataSetVersion = currentDataSet->dataSetMetaData.configurationVersion;
- UA_PubSubDataSetWriter_generateKeyFrameMessage(server, dataSetMessage, dataSetWriter);
+ dataSetWriter->connectedDataSetVersion =
+ currentDataSet->dataSetMetaData.configurationVersion;
+ UA_PubSubDataSetWriter_generateKeyFrameMessage(server, dataSetMessage,
+ dataSetWriter);
dataSetWriter->deltaFrameCounter = 0;
return UA_STATUSCODE_GOOD;
}
@@ -29829,7 +29195,8 @@ UA_DataSetWriter_generateDataSetMessage(UA_Server *server, UA_DataSetMessage *da
* field. */
if(currentDataSet->fieldSize > 1 && dataSetWriter->deltaFrameCounter > 0 &&
dataSetWriter->deltaFrameCounter <= dataSetWriter->config.keyFrameCount) {
- UA_PubSubDataSetWriter_generateDeltaFrameMessage(server, dataSetMessage, dataSetWriter);
+ UA_PubSubDataSetWriter_generateDeltaFrameMessage(server, dataSetMessage,
+ dataSetWriter);
dataSetWriter->deltaFrameCounter++;
return UA_STATUSCODE_GOOD;
}
@@ -29838,58 +29205,799 @@ UA_DataSetWriter_generateDataSetMessage(UA_Server *server, UA_DataSetMessage *da
#endif
}
- return UA_PubSubDataSetWriter_generateKeyFrameMessage(server, dataSetMessage, dataSetWriter);
+ return UA_PubSubDataSetWriter_generateKeyFrameMessage(server, dataSetMessage,
+ dataSetWriter);
}
+#endif /* UA_ENABLE_PUBSUB */
+
+/**** amalgamated original file "/src/pubsub/ua_pubsub_writergroup.c" ****/
+
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Copyright (c) 2017-2019 Fraunhofer IOSB (Author: Andreas Ebner)
+ * Copyright (c) 2019 Fraunhofer IOSB (Author: Julius Pfrommer)
+ * Copyright (c) 2019 Kalycito Infotech Private Limited
+ * Copyright (c) 2020 Yannick Wallerer, Siemens AG
+ * Copyright (c) 2020 Thomas Fischer, Siemens AG
+ * Copyright (c) 2021 Fraunhofer IOSB (Author: Jan Hermes)
+ */
+
+
+#ifdef UA_ENABLE_PUBSUB /* conditional compilation */
+
+
+#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL
+#endif
+
+#define UA_MAX_STACKBUF 128 /* Max size of network messages on the stack */
+
+static void
+UA_WriterGroup_clear(UA_Server *server, UA_WriterGroup *writerGroup);
+
static UA_StatusCode
-sendNetworkMessageJson(UA_PubSubConnection *connection, UA_DataSetMessage *dsm,
- UA_UInt16 *writerIds, UA_Byte dsmCount,
- UA_ExtensionObject *transportSettings) {
- UA_StatusCode retval = UA_STATUSCODE_BADNOTSUPPORTED;
+generateNetworkMessage(UA_PubSubConnection *connection, UA_WriterGroup *wg,
+ UA_DataSetMessage *dsm, UA_UInt16 *writerIds, UA_Byte dsmCount,
+ UA_ExtensionObject *messageSettings,
+ UA_ExtensionObject *transportSettings,
+ UA_NetworkMessage *networkMessage);
+
+UA_StatusCode
+UA_Server_addWriterGroup(UA_Server *server, const UA_NodeId connection,
+ const UA_WriterGroupConfig *writerGroupConfig,
+ UA_NodeId *writerGroupIdentifier) {
+ if(!writerGroupConfig)
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+
+ /* Search the connection by the given connectionIdentifier */
+ UA_PubSubConnection *currentConnectionContext =
+ UA_PubSubConnection_findConnectionbyId(server, connection);
+ if(!currentConnectionContext)
+ return UA_STATUSCODE_BADNOTFOUND;
+
+ if(currentConnectionContext->configurationFrozen){
+ UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Adding WriterGroup failed. PubSubConnection is frozen.");
+ return UA_STATUSCODE_BADCONFIGURATIONERROR;
+ }
+
+ /* Validate messageSettings type */
+ const UA_ExtensionObject *ms = &writerGroupConfig->messageSettings;
+ if(ms->content.decoded.type) {
+ if(writerGroupConfig->encodingMimeType == UA_PUBSUB_ENCODING_JSON &&
+ (ms->encoding != UA_EXTENSIONOBJECT_DECODED ||
+ ms->content.decoded.type != &UA_TYPES[UA_TYPES_JSONWRITERGROUPMESSAGEDATATYPE])) {
+ return UA_STATUSCODE_BADTYPEMISMATCH;
+ }
+
+ if(writerGroupConfig->encodingMimeType == UA_PUBSUB_ENCODING_UADP &&
+ (ms->encoding != UA_EXTENSIONOBJECT_DECODED ||
+ ms->content.decoded.type != &UA_TYPES[UA_TYPES_UADPWRITERGROUPMESSAGEDATATYPE])) {
+ return UA_STATUSCODE_BADTYPEMISMATCH;
+ }
+ }
+
+ /* Allocate new WriterGroup */
+ UA_WriterGroup *newWriterGroup = (UA_WriterGroup*)UA_calloc(1, sizeof(UA_WriterGroup));
+ if(!newWriterGroup)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+
+ newWriterGroup->componentType = UA_PUBSUB_COMPONENT_WRITERGROUP;
+ newWriterGroup->linkedConnection = currentConnectionContext;
+
+ /* Deep copy of the config */
+ UA_WriterGroupConfig *newConfig = &newWriterGroup->config;
+ UA_StatusCode res = UA_WriterGroupConfig_copy(writerGroupConfig, newConfig);
+ if(res != UA_STATUSCODE_GOOD) {
+ UA_free(newWriterGroup);
+ return res;
+ }
+
+ /* Create the datatype value if not present */
+ if(!newConfig->messageSettings.content.decoded.type) {
+ UA_UadpWriterGroupMessageDataType *wgm = UA_UadpWriterGroupMessageDataType_new();
+ newConfig->messageSettings.content.decoded.data = wgm;
+ newConfig->messageSettings.content.decoded.type =
+ &UA_TYPES[UA_TYPES_UADPWRITERGROUPMESSAGEDATATYPE];
+ newConfig->messageSettings.encoding = UA_EXTENSIONOBJECT_DECODED;
+ }
+
+ /* Attach to the connection */
+ LIST_INSERT_HEAD(&currentConnectionContext->writerGroups, newWriterGroup, listEntry);
+ currentConnectionContext->writerGroupsSize++;
+
+ /* Add representation / create unique identifier */
+#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL
+ res = addWriterGroupRepresentation(server, newWriterGroup);
+#else
+ UA_PubSubManager_generateUniqueNodeId(&server->pubSubManager,
+ &newWriterGroup->identifier);
+#endif
+ if(writerGroupIdentifier)
+ UA_NodeId_copy(&newWriterGroup->identifier, writerGroupIdentifier);
+ return res;
+}
+
+UA_StatusCode
+UA_Server_removeWriterGroup(UA_Server *server, const UA_NodeId writerGroup) {
+ UA_WriterGroup *wg = UA_WriterGroup_findWGbyId(server, writerGroup);
+ if(!wg)
+ return UA_STATUSCODE_BADNOTFOUND;
+
+ if(wg->configurationFrozen) {
+ UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Delete WriterGroup failed. WriterGroup is frozen.");
+ return UA_STATUSCODE_BADCONFIGURATIONERROR;
+ }
+
+ UA_PubSubConnection *connection = wg->linkedConnection;
+ if(!connection)
+ return UA_STATUSCODE_BADNOTFOUND;
+
+ if(connection->configurationFrozen) {
+ UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Delete WriterGroup failed. PubSubConnection is frozen.");
+ return UA_STATUSCODE_BADCONFIGURATIONERROR;
+ }
+
+ if(wg->state == UA_PUBSUBSTATE_OPERATIONAL) {
+ /* Unregister the publish callback */
+ if(wg->config.pubsubManagerCallback.removeCustomCallback)
+ wg->config.pubsubManagerCallback.
+ removeCustomCallback(server, wg->identifier, wg->publishCallbackId);
+ else
+ UA_PubSubManager_removeRepeatedPubSubCallback(server, wg->publishCallbackId);
+
+ }
+
+ UA_DataSetWriter *dsw, *dsw_tmp;
+ LIST_FOREACH_SAFE(dsw, &wg->writers, listEntry, dsw_tmp) {
+ UA_DataSetWriter_remove(server, wg, dsw);
+ }
+
+ connection->writerGroupsSize--;
+#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL
+ removeGroupRepresentation(server, wg);
+#endif
+
+ UA_WriterGroup_clear(server, wg);
+ LIST_REMOVE(wg, listEntry);
+ UA_free(wg);
+ return UA_STATUSCODE_GOOD;
+}
+
+UA_StatusCode
+UA_Server_freezeWriterGroupConfiguration(UA_Server *server,
+ const UA_NodeId writerGroup) {
+ UA_WriterGroup *wg = UA_WriterGroup_findWGbyId(server, writerGroup);
+ if(!wg)
+ return UA_STATUSCODE_BADNOTFOUND;
+
+ /* PubSubConnection freezeCounter++ */
+ UA_PubSubConnection *pubSubConnection = wg->linkedConnection;
+ pubSubConnection->configurationFreezeCounter++;
+ pubSubConnection->configurationFrozen = true;
+
+ /* WriterGroup freeze */
+ wg->configurationFrozen = true;
+
+ /* DataSetWriter freeze */
+ UA_DataSetWriter *dataSetWriter;
+ LIST_FOREACH(dataSetWriter, &wg->writers, listEntry) {
+ dataSetWriter->configurationFrozen = true;
+ /* PublishedDataSet freezeCounter++ */
+ UA_PublishedDataSet *publishedDataSet =
+ UA_PublishedDataSet_findPDSbyId(server, dataSetWriter->connectedDataSet);
+ publishedDataSet->configurationFreezeCounter++;
+ publishedDataSet->configurationFrozen = true;
+ /* DataSetFields freeze */
+ UA_DataSetField *dataSetField;
+ TAILQ_FOREACH(dataSetField, &publishedDataSet->fields, listEntry) {
+ dataSetField->configurationFrozen = true;
+ }
+ }
+
+ if(wg->config.rtLevel != UA_PUBSUB_RT_FIXED_SIZE)
+ return UA_STATUSCODE_GOOD;
+
+ /* Freeze the RT writer configuration */
+ size_t dsmCount = 0;
+ if(wg->config.encodingMimeType != UA_PUBSUB_ENCODING_UADP) {
+ UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "PubSub-RT configuration fail: Non-RT capable encoding.");
+ return UA_STATUSCODE_BADNOTSUPPORTED;
+ }
+
+ //TODO Clarify: should we only allow = maxEncapsulatedDataSetMessageCount == 1 with RT?
+ //TODO Clarify: Behaviour if the finale size is more than MTU
+
+ /* Generate data set messages */
+ UA_STACKARRAY(UA_UInt16, dsWriterIds, wg->writersCount);
+ UA_STACKARRAY(UA_DataSetMessage, dsmStore, wg->writersCount);
+ UA_StatusCode res = UA_STATUSCODE_GOOD;
+ UA_DataSetWriter *dsw;
+ LIST_FOREACH(dsw, &wg->writers, listEntry) {
+ /* Find the dataset */
+ UA_PublishedDataSet *pds =
+ UA_PublishedDataSet_findPDSbyId(server, dsw->connectedDataSet);
+ if(!pds) {
+ UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "PubSub Publish: PublishedDataSet not found");
+ continue;
+ }
+ if(pds->promotedFieldsCount > 0) {
+ UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "PubSub-RT configuration fail: PDS contains promoted fields.");
+ return UA_STATUSCODE_BADNOTSUPPORTED;
+ }
+
+ /* Test the DataSetFields */
+ UA_DataSetField *dsf;
+ TAILQ_FOREACH(dsf, &pds->fields, listEntry) {
+ const UA_VariableNode *rtNode = (const UA_VariableNode *)
+ UA_NODESTORE_GET(server, &dsf->config.field.variable.publishParameters.publishedVariable);
+ if(rtNode != NULL && rtNode->valueBackend.backendType != UA_VALUEBACKENDTYPE_EXTERNAL) {
+ UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "PubSub-RT configuration fail: PDS contains field without external data source.");
+ UA_NODESTORE_RELEASE(server, (const UA_Node *) rtNode);
+ return UA_STATUSCODE_BADNOTSUPPORTED;
+ }
+ UA_NODESTORE_RELEASE(server, (const UA_Node *) rtNode);
+ if((UA_NodeId_equal(&dsf->fieldMetaData.dataType, &UA_TYPES[UA_TYPES_STRING].typeId) ||
+ UA_NodeId_equal(&dsf->fieldMetaData.dataType,
+ &UA_TYPES[UA_TYPES_BYTESTRING].typeId)) &&
+ dsf->fieldMetaData.maxStringLength == 0) {
+ UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "PubSub-RT configuration fail: "
+ "PDS contains String/ByteString with dynamic length.");
+ return UA_STATUSCODE_BADNOTSUPPORTED;
+ } else if(!UA_DataType_isNumeric(UA_findDataType(&dsf->fieldMetaData.dataType)) &&
+ !UA_NodeId_equal(&dsf->fieldMetaData.dataType, &UA_TYPES[UA_TYPES_BOOLEAN].typeId)) {
+ UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "PubSub-RT configuration fail: "
+ "PDS contains variable with dynamic size.");
+ return UA_STATUSCODE_BADNOTSUPPORTED;
+ }
+ }
+
+ /* Generate the DSM */
+ res = UA_DataSetWriter_generateDataSetMessage(server, &dsmStore[dsmCount], dsw);
+ if(res != UA_STATUSCODE_GOOD) {
+ UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "PubSub RT Offset calculation: DataSetMessage buffering failed");
+ continue;
+ }
+
+ dsWriterIds[dsmCount] = dsw->config.dataSetWriterId;
+ dsmCount++;
+ }
+
+ /* Define variables here for goto */
+ size_t msgSize;
+ UA_ByteString buf;
+ UA_NetworkMessage networkMessage;
+ const UA_Byte *bufEnd;
+ UA_Byte *bufPos;
+
+ if(res != UA_STATUSCODE_GOOD)
+ goto cleanup_dsm;
+
+ memset(&networkMessage, 0, sizeof(networkMessage));
+ res = generateNetworkMessage(pubSubConnection, wg, dsmStore, dsWriterIds,
+ (UA_Byte) dsmCount, &wg->config.messageSettings,
+ &wg->config.transportSettings, &networkMessage);
+ if(res != UA_STATUSCODE_GOOD)
+ goto cleanup_dsm;
+
+ memset(&wg->bufferedMessage, 0, sizeof(UA_NetworkMessageOffsetBuffer));
+ UA_NetworkMessage_calcSizeBinary(&networkMessage, &wg->bufferedMessage);
+
+ /* Allocate the buffer. Allocate on the stack if the buffer is small. */
+ msgSize = UA_NetworkMessage_calcSizeBinary(&networkMessage, NULL);
+ res = UA_ByteString_allocBuffer(&buf, msgSize);
+ if(res != UA_STATUSCODE_GOOD)
+ goto cleanup;
+ wg->bufferedMessage.buffer = buf;
+
+ /* Encode the NetworkMessage */
+ bufEnd = &wg->bufferedMessage.buffer.data[wg->bufferedMessage.buffer.length];
+ bufPos = wg->bufferedMessage.buffer.data;
+ UA_NetworkMessage_encodeBinary(&networkMessage, &bufPos, bufEnd, NULL);
+
+ cleanup:
+ UA_free(networkMessage.payload.dataSetPayload.sizes);
+
+ /* Clean up DSM */
+ cleanup_dsm:
+ for(size_t i = 0; i < dsmCount; i++){
+ UA_free(dsmStore[i].data.keyFrameData.dataSetFields);
+#ifdef UA_ENABLE_JSON_ENCODING
+ UA_Array_delete(dsmStore[i].data.keyFrameData.fieldNames,
+ dsmStore[i].data.keyFrameData.fieldCount,
+ &UA_TYPES[UA_TYPES_STRING]);
+#endif
+ }
+
+ return res;
+}
+
+UA_StatusCode
+UA_Server_unfreezeWriterGroupConfiguration(UA_Server *server,
+ const UA_NodeId writerGroup) {
+ UA_WriterGroup *wg = UA_WriterGroup_findWGbyId(server, writerGroup);
+ if(!wg)
+ return UA_STATUSCODE_BADNOTFOUND;
+ //if(wg->config.rtLevel == UA_PUBSUB_RT_NONE){
+ // UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ // "PubSub configuration freeze without RT configuration has no effect.");
+ // return UA_STATUSCODE_BADCONFIGURATIONERROR;
+ //}
+ //PubSubConnection freezeCounter--
+ UA_PubSubConnection *pubSubConnection = wg->linkedConnection;
+ pubSubConnection->configurationFreezeCounter--;
+ if(pubSubConnection->configurationFreezeCounter == 0){
+ pubSubConnection->configurationFrozen = UA_FALSE;
+ }
+ //WriterGroup unfreeze
+ wg->configurationFrozen = UA_FALSE;
+ //DataSetWriter unfreeze
+ UA_DataSetWriter *dataSetWriter;
+ LIST_FOREACH(dataSetWriter, &wg->writers, listEntry) {
+ UA_PublishedDataSet *publishedDataSet =
+ UA_PublishedDataSet_findPDSbyId(server, dataSetWriter->connectedDataSet);
+ //PublishedDataSet freezeCounter--
+ publishedDataSet->configurationFreezeCounter--;
+ if(publishedDataSet->configurationFreezeCounter == 0){
+ publishedDataSet->configurationFrozen = UA_FALSE;
+ UA_DataSetField *dataSetField;
+ TAILQ_FOREACH(dataSetField, &publishedDataSet->fields, listEntry){
+ dataSetField->configurationFrozen = UA_FALSE;
+ }
+ }
+ dataSetWriter->configurationFrozen = UA_FALSE;
+ }
+ if(wg->config.rtLevel == UA_PUBSUB_RT_FIXED_SIZE)
+ UA_ByteString_clear(&wg->bufferedMessage.buffer);
+
+ return UA_STATUSCODE_GOOD;
+}
+
+UA_StatusCode
+UA_Server_setWriterGroupOperational(UA_Server *server,
+ const UA_NodeId writerGroup) {
+ UA_WriterGroup *wg = UA_WriterGroup_findWGbyId(server, writerGroup);
+ if(!wg)
+ return UA_STATUSCODE_BADNOTFOUND;
+ return UA_WriterGroup_setPubSubState(server, UA_PUBSUBSTATE_OPERATIONAL, wg);
+}
+
+UA_StatusCode
+UA_Server_setWriterGroupDisabled(UA_Server *server,
+ const UA_NodeId writerGroup) {
+ UA_WriterGroup *wg = UA_WriterGroup_findWGbyId(server, writerGroup);
+ if(!wg)
+ return UA_STATUSCODE_BADNOTFOUND;
+ return UA_WriterGroup_setPubSubState(server, UA_PUBSUBSTATE_DISABLED, wg);
+}
+
+UA_StatusCode
+UA_WriterGroupConfig_copy(const UA_WriterGroupConfig *src,
+ UA_WriterGroupConfig *dst){
+ UA_StatusCode res = UA_STATUSCODE_GOOD;
+ memcpy(dst, src, sizeof(UA_WriterGroupConfig));
+ res |= UA_String_copy(&src->name, &dst->name);
+ res |= UA_ExtensionObject_copy(&src->transportSettings, &dst->transportSettings);
+ res |= UA_ExtensionObject_copy(&src->messageSettings, &dst->messageSettings);
+ if(src->groupPropertiesSize > 0) {
+ dst->groupProperties = (UA_KeyValuePair*)
+ UA_calloc(src->groupPropertiesSize, sizeof(UA_KeyValuePair));
+ if(!dst->groupProperties)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ for(size_t i = 0; i < src->groupPropertiesSize; i++) {
+ res |= UA_KeyValuePair_copy(&src->groupProperties[i], &dst->groupProperties[i]);
+ }
+ }
+ if(res != UA_STATUSCODE_GOOD)
+ UA_WriterGroupConfig_clear(dst);
+ return res;
+}
+
+UA_StatusCode
+UA_Server_getWriterGroupConfig(UA_Server *server, const UA_NodeId writerGroup,
+ UA_WriterGroupConfig *config) {
+ if(!config)
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+ UA_WriterGroup *currentWG = UA_WriterGroup_findWGbyId(server, writerGroup);
+ if(!currentWG)
+ return UA_STATUSCODE_BADNOTFOUND;
+ return UA_WriterGroupConfig_copy(&currentWG->config, config);
+}
+
+UA_StatusCode
+UA_Server_updateWriterGroupConfig(UA_Server *server, UA_NodeId writerGroupIdentifier,
+ const UA_WriterGroupConfig *config){
+ if(!config)
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+
+ UA_WriterGroup *currentWriterGroup =
+ UA_WriterGroup_findWGbyId(server, writerGroupIdentifier);
+ if(!currentWriterGroup)
+ return UA_STATUSCODE_BADNOTFOUND;
+
+ if(currentWriterGroup->configurationFrozen){
+ UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Modify WriterGroup failed. WriterGroup is frozen.");
+ return UA_STATUSCODE_BADCONFIGURATIONERROR;
+ }
+
+ //The update functionality will be extended during the next PubSub batches.
+ //Currently is only a change of the publishing interval possible.
+ if(currentWriterGroup->config.maxEncapsulatedDataSetMessageCount != config->maxEncapsulatedDataSetMessageCount) {
+ currentWriterGroup->config.maxEncapsulatedDataSetMessageCount = config->maxEncapsulatedDataSetMessageCount;
+ if(currentWriterGroup->config.messageSettings.encoding == UA_EXTENSIONOBJECT_ENCODED_NOBODY) {
+ UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "MaxEncapsulatedDataSetMessag need enabled 'PayloadHeader' within the message settings.");
+ }
+ }
+
+ if(currentWriterGroup->config.publishingInterval != config->publishingInterval) {
+ if(currentWriterGroup->config.rtLevel == UA_PUBSUB_RT_NONE &&
+ currentWriterGroup->state == UA_PUBSUBSTATE_OPERATIONAL) {
+ if(currentWriterGroup->config.pubsubManagerCallback.removeCustomCallback)
+ currentWriterGroup->config.pubsubManagerCallback.
+ removeCustomCallback(server, currentWriterGroup->identifier,
+ currentWriterGroup->publishCallbackId);
+ else
+ UA_PubSubManager_removeRepeatedPubSubCallback(server, currentWriterGroup->publishCallbackId);
+
+ currentWriterGroup->config.publishingInterval = config->publishingInterval;
+ UA_WriterGroup_addPublishCallback(server, currentWriterGroup);
+ } else {
+ currentWriterGroup->config.publishingInterval = config->publishingInterval;
+ }
+ }
+
+ if(currentWriterGroup->config.priority != config->priority) {
+ UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "No or unsupported WriterGroup update.");
+ }
+
+ return UA_STATUSCODE_GOOD;
+}
+
+UA_StatusCode
+UA_Server_WriterGroup_getState(UA_Server *server, UA_NodeId writerGroupIdentifier,
+ UA_PubSubState *state) {
+ if((server == NULL) || (state == NULL))
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+ UA_WriterGroup *currentWriterGroup =
+ UA_WriterGroup_findWGbyId(server, writerGroupIdentifier);
+ if(currentWriterGroup == NULL)
+ return UA_STATUSCODE_BADNOTFOUND;
+ *state = currentWriterGroup->state;
+ return UA_STATUSCODE_GOOD;
+}
+
+UA_WriterGroup *
+UA_WriterGroup_findWGbyId(UA_Server *server, UA_NodeId identifier) {
+ UA_PubSubConnection *tmpConnection;
+ TAILQ_FOREACH(tmpConnection, &server->pubSubManager.connections, listEntry) {
+ UA_WriterGroup *tmpWriterGroup;
+ LIST_FOREACH(tmpWriterGroup, &tmpConnection->writerGroups, listEntry) {
+ if(UA_NodeId_equal(&identifier, &tmpWriterGroup->identifier))
+ return tmpWriterGroup;
+ }
+ }
+ return NULL;
+}
+
+#ifdef UA_ENABLE_PUBSUB_ENCRYPTION
+UA_StatusCode
+UA_Server_setWriterGroupEncryptionKeys(UA_Server *server, const UA_NodeId writerGroup,
+ UA_UInt32 securityTokenId,
+ const UA_ByteString signingKey,
+ const UA_ByteString encryptingKey,
+ const UA_ByteString keyNonce) {
+ UA_WriterGroup *wg = UA_WriterGroup_findWGbyId(server, writerGroup);
+ if(!wg)
+ return UA_STATUSCODE_BADNOTFOUND;
+
+ if(!wg->config.securityPolicy) {
+ UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "No SecurityPolicy configured for the WriterGroup");
+ return UA_STATUSCODE_BADINTERNALERROR;
+ }
+
+ if(securityTokenId != wg->securityTokenId) {
+ wg->securityTokenId = securityTokenId;
+ wg->nonceSequenceNumber = 1;
+ }
+
+ /* Create a new context */
+ if(!wg->securityPolicyContext) {
+ return wg->config.securityPolicy->
+ newContext(wg->config.securityPolicy->policyContext,
+ &signingKey, &encryptingKey, &keyNonce,
+ &wg->securityPolicyContext);
+ }
+
+ /* Update the context */
+ return wg->config.securityPolicy->
+ setSecurityKeys(wg->securityPolicyContext, &signingKey, &encryptingKey, &keyNonce);
+}
+#endif
+
+void
+UA_WriterGroupConfig_clear(UA_WriterGroupConfig *writerGroupConfig){
+ UA_String_clear(&writerGroupConfig->name);
+ UA_ExtensionObject_clear(&writerGroupConfig->transportSettings);
+ UA_ExtensionObject_clear(&writerGroupConfig->messageSettings);
+ UA_Array_delete(writerGroupConfig->groupProperties,
+ writerGroupConfig->groupPropertiesSize,
+ &UA_TYPES[UA_TYPES_KEYVALUEPAIR]);
+ writerGroupConfig->groupProperties = NULL;
+}
+
+static void
+UA_WriterGroup_clear(UA_Server *server, UA_WriterGroup *writerGroup) {
+ UA_WriterGroupConfig_clear(&writerGroup->config);
+ UA_NodeId_clear(&writerGroup->identifier);
+
+ /* Delete all writers */
+ UA_DataSetWriter *dataSetWriter, *tmpDataSetWriter;
+ LIST_FOREACH_SAFE(dataSetWriter, &writerGroup->writers, listEntry, tmpDataSetWriter){
+ UA_Server_removeDataSetWriter(server, dataSetWriter->identifier);
+ }
+
+ if(writerGroup->bufferedMessage.offsetsSize > 0){
+ for(size_t i = 0; i < writerGroup->bufferedMessage.offsetsSize; i++) {
+ if((writerGroup->bufferedMessage.offsets[i].contentType == UA_PUBSUB_OFFSETTYPE_PAYLOAD_VARIANT) ||
+ (writerGroup->bufferedMessage.offsets[i].contentType == UA_PUBSUB_OFFSETTYPE_PAYLOAD_RAW)) {
+ UA_DataValue_delete(writerGroup->bufferedMessage.offsets[i].offsetData.value.value);
+ } else if(writerGroup->bufferedMessage.offsets[i].contentType == UA_PUBSUB_OFFSETTYPE_NETWORKMESSAGE_FIELDENCDODING) {
+ writerGroup->bufferedMessage.offsets[i].offsetData.value.value->value.data = NULL;
+ UA_DataValue_delete(writerGroup->bufferedMessage.offsets[i].offsetData.value.value);
+ }
+ }
+ UA_ByteString_clear(&writerGroup->bufferedMessage.buffer);
+ UA_free(writerGroup->bufferedMessage.offsets);
+ }
+
+#ifdef UA_ENABLE_PUBSUB_ENCRYPTION
+ if(writerGroup->config.securityPolicy && writerGroup->securityPolicyContext) {
+ writerGroup->config.securityPolicy->deleteContext(writerGroup->securityPolicyContext);
+ writerGroup->securityPolicyContext = NULL;
+ }
+#endif
+}
+
+UA_StatusCode
+UA_WriterGroup_setPubSubState(UA_Server *server, UA_PubSubState state,
+ UA_WriterGroup *writerGroup) {
+ UA_DataSetWriter *dataSetWriter;
+ switch(state) {
+ case UA_PUBSUBSTATE_DISABLED:
+ switch (writerGroup->state){
+ case UA_PUBSUBSTATE_DISABLED:
+ return UA_STATUSCODE_GOOD;
+ case UA_PUBSUBSTATE_PAUSED:
+ break;
+ case UA_PUBSUBSTATE_OPERATIONAL:
+ if(writerGroup->config.pubsubManagerCallback.removeCustomCallback)
+ writerGroup->config.pubsubManagerCallback.
+ removeCustomCallback(server, writerGroup->identifier, writerGroup->publishCallbackId);
+ else
+ UA_PubSubManager_removeRepeatedPubSubCallback(server, writerGroup->publishCallbackId);
+
+ LIST_FOREACH(dataSetWriter, &writerGroup->writers, listEntry){
+ UA_DataSetWriter_setPubSubState(server, UA_PUBSUBSTATE_DISABLED, dataSetWriter);
+ }
+ writerGroup->state = UA_PUBSUBSTATE_DISABLED;
+ break;
+ case UA_PUBSUBSTATE_ERROR:
+ break;
+ default:
+ UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Received unknown PubSub state!");
+ }
+ break;
+ case UA_PUBSUBSTATE_PAUSED:
+ switch (writerGroup->state) {
+ case UA_PUBSUBSTATE_DISABLED:
+ break;
+ case UA_PUBSUBSTATE_PAUSED:
+ return UA_STATUSCODE_GOOD;
+ case UA_PUBSUBSTATE_OPERATIONAL:
+ break;
+ case UA_PUBSUBSTATE_ERROR:
+ break;
+ default:
+ UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Received unknown PubSub state!");
+ }
+ break;
+ case UA_PUBSUBSTATE_OPERATIONAL:
+ switch (writerGroup->state) {
+ case UA_PUBSUBSTATE_DISABLED:
+ writerGroup->state = UA_PUBSUBSTATE_OPERATIONAL;
+ if(writerGroup->config.pubsubManagerCallback.removeCustomCallback)
+ writerGroup->config.pubsubManagerCallback.
+ removeCustomCallback(server, writerGroup->identifier,
+ writerGroup->publishCallbackId);
+ else
+ UA_PubSubManager_removeRepeatedPubSubCallback(server, writerGroup->publishCallbackId);
+
+ LIST_FOREACH(dataSetWriter, &writerGroup->writers, listEntry){
+ UA_DataSetWriter_setPubSubState(server, UA_PUBSUBSTATE_OPERATIONAL,
+ dataSetWriter);
+ }
+ UA_WriterGroup_addPublishCallback(server, writerGroup);
+ break;
+ case UA_PUBSUBSTATE_PAUSED:
+ break;
+ case UA_PUBSUBSTATE_OPERATIONAL:
+ return UA_STATUSCODE_GOOD;
+ case UA_PUBSUBSTATE_ERROR:
+ break;
+ default:
+ UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Received unknown PubSub state!");
+ }
+ break;
+ case UA_PUBSUBSTATE_ERROR: {
+ switch (writerGroup->state){
+ case UA_PUBSUBSTATE_DISABLED:
+ break;
+ case UA_PUBSUBSTATE_PAUSED:
+ break;
+ case UA_PUBSUBSTATE_OPERATIONAL:
+ UA_PubSubManager_removeRepeatedPubSubCallback(server, writerGroup->publishCallbackId);
+ LIST_FOREACH(dataSetWriter, &writerGroup->writers, listEntry){
+ UA_DataSetWriter_setPubSubState(server, UA_PUBSUBSTATE_ERROR, dataSetWriter);
+ }
+ break;
+ case UA_PUBSUBSTATE_ERROR:
+ return UA_STATUSCODE_GOOD;
+ default:
+ UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Received unknown PubSub state!");
+ }
+ writerGroup->state = UA_PUBSUBSTATE_ERROR;
+ /* TODO: WIP - example usage of pubsubStateChangeCallback -> inform
+ * application about error state, reason param necessary */
+ UA_ServerConfig *pConfig = UA_Server_getConfig(server);
+ if(pConfig->pubSubConfig.stateChangeCallback != 0) {
+ pConfig->pubSubConfig.
+ stateChangeCallback(&writerGroup->identifier, UA_PUBSUBSTATE_ERROR,
+ UA_STATUSCODE_BADINTERNALERROR);
+ }
+ break;
+ }
+ default:
+ UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Received unknown PubSub state!");
+ }
+ return UA_STATUSCODE_GOOD;
+}
+
+#ifdef UA_ENABLE_PUBSUB_ENCRYPTION
+static UA_StatusCode
+encryptAndSign(UA_WriterGroup *wg, const UA_NetworkMessage *nm,
+ UA_Byte *signStart, UA_Byte *encryptStart,
+ UA_Byte *msgEnd) {
+ UA_StatusCode rv;
+ void *channelContext = wg->securityPolicyContext;
+
+ if(nm->securityHeader.networkMessageEncrypted) {
+ /* Set the temporary MessageNonce in the SecurityPolicy */
+ rv = wg->config.securityPolicy->setMessageNonce(channelContext,
+ &nm->securityHeader.messageNonce);
+ UA_CHECK_STATUS(rv, return rv);
+
+ /* The encryption is done in-place, no need to encode again */
+ UA_ByteString toBeEncrypted =
+ {(uintptr_t)msgEnd - (uintptr_t)encryptStart, encryptStart};
+ rv = wg->config.securityPolicy->symmetricModule.cryptoModule.encryptionAlgorithm.
+ encrypt(channelContext, &toBeEncrypted);
+ UA_CHECK_STATUS(rv, return rv);
+ }
+
+ if(nm->securityHeader.networkMessageSigned) {
+ UA_ByteString toBeSigned = {(uintptr_t)msgEnd - (uintptr_t)signStart,
+ signStart};
+
+ size_t sigSize = wg->config.securityPolicy->symmetricModule.cryptoModule.
+ signatureAlgorithm.getLocalSignatureSize(channelContext);
+ UA_ByteString signature = {sigSize, msgEnd};
+
+ rv = wg->config.securityPolicy->symmetricModule.cryptoModule.
+ signatureAlgorithm.sign(channelContext, &toBeSigned, &signature);
+ UA_CHECK_STATUS(rv, return rv);
+ }
+ return UA_STATUSCODE_GOOD;
+}
+#endif
+
+static UA_StatusCode
+encodeNetworkMessage(UA_WriterGroup *wg, UA_NetworkMessage *nm,
+ UA_ByteString *buf) {
+ UA_Byte *bufPos = buf->data;
+ UA_Byte *bufEnd = &buf->data[buf->length];
+
+#ifdef UA_ENABLE_PUBSUB_ENCRYPTION
+ UA_Byte *networkMessageStart = bufPos;
+#endif
+ UA_StatusCode rv = UA_NetworkMessage_encodeHeaders(nm, &bufPos, bufEnd);
+ UA_CHECK_STATUS(rv, return rv);
+
+#ifdef UA_ENABLE_PUBSUB_ENCRYPTION
+ UA_Byte *payloadStart = bufPos;
+#endif
+ rv = UA_NetworkMessage_encodePayload(nm, &bufPos, bufEnd);
+ UA_CHECK_STATUS(rv, return rv);
+
+ rv = UA_NetworkMessage_encodeFooters(nm, &bufPos, bufEnd);
+ UA_CHECK_STATUS(rv, return rv);
+
+#ifdef UA_ENABLE_PUBSUB_ENCRYPTION
+ /* Encrypt and Sign the message */
+ UA_Byte *footerEnd = bufPos;
+ rv = encryptAndSign(wg, nm, networkMessageStart, payloadStart, footerEnd);
+ UA_CHECK_STATUS(rv, return rv);
+#endif
+
+ return UA_STATUSCODE_GOOD;
+}
+
#ifdef UA_ENABLE_JSON_ENCODING
+static UA_StatusCode
+sendNetworkMessageJson(UA_PubSubConnection *connection, UA_WriterGroup *wg,
+ UA_DataSetMessage *dsm, UA_UInt16 *writerIds, UA_Byte dsmCount) {
+ /* Prepare the NetworkMessage */
UA_NetworkMessage nm;
memset(&nm, 0, sizeof(UA_NetworkMessage));
nm.version = 1;
nm.networkMessageType = UA_NETWORKMESSAGE_DATASET;
nm.payloadHeaderEnabled = true;
-
nm.payloadHeader.dataSetPayloadHeader.count = dsmCount;
nm.payloadHeader.dataSetPayloadHeader.dataSetWriterIds = writerIds;
nm.payload.dataSetPayload.dataSetMessages = dsm;
+ /* Compute the message length */
+ size_t msgSize = UA_NetworkMessage_calcSizeJson(&nm, NULL, 0, NULL, 0, true);
+
/* Allocate the buffer. Allocate on the stack if the buffer is small. */
UA_ByteString buf;
- size_t msgSize = UA_NetworkMessage_calcSizeJson(&nm, NULL, 0, NULL, 0, true);
- size_t stackSize = 1;
- if(msgSize <= UA_MAX_STACKBUF)
- stackSize = msgSize;
- UA_STACKARRAY(UA_Byte, stackBuf, stackSize);
+ UA_Byte stackBuf[UA_MAX_STACKBUF];
buf.data = stackBuf;
buf.length = msgSize;
+ UA_StatusCode res = UA_STATUSCODE_GOOD;
if(msgSize > UA_MAX_STACKBUF) {
- retval = UA_ByteString_allocBuffer(&buf, msgSize);
- if(retval != UA_STATUSCODE_GOOD)
- return retval;
+ res = UA_ByteString_allocBuffer(&buf, msgSize);
+ if(res != UA_STATUSCODE_GOOD)
+ return res;
}
/* Encode the message */
UA_Byte *bufPos = buf.data;
- memset(bufPos, 0, msgSize);
- const UA_Byte *bufEnd = &buf.data[buf.length];
- retval = UA_NetworkMessage_encodeJson(&nm, &bufPos, &bufEnd, NULL, 0, NULL, 0, true);
- if(retval != UA_STATUSCODE_GOOD) {
- if(msgSize > UA_MAX_STACKBUF)
- UA_ByteString_clear(&buf);
- return retval;
- }
+ const UA_Byte *bufEnd = &buf.data[msgSize];
+ res = UA_NetworkMessage_encodeJson(&nm, &bufPos, &bufEnd, NULL, 0, NULL, 0, true);
+ if(res != UA_STATUSCODE_GOOD)
+ goto cleanup;
+ UA_assert(bufPos == bufEnd);
/* Send the prepared messages */
- retval = connection->channel->send(connection->channel, transportSettings, &buf);
+ res = connection->channel->send(connection->channel,
+ &wg->config.transportSettings, &buf);
+
+ cleanup:
if(msgSize > UA_MAX_STACKBUF)
UA_ByteString_clear(&buf);
-#endif
- return retval;
+ return res;
}
+#endif
static UA_StatusCode
generateNetworkMessage(UA_PubSubConnection *connection, UA_WriterGroup *wg,
@@ -29936,19 +30044,56 @@ generateNetworkMessage(UA_PubSubConnection *connection, UA_WriterGroup *wg,
networkMessage->promotedFieldsEnabled =
((u64)wgm->networkMessageContentMask &
(u64)UA_UADPNETWORKMESSAGECONTENTMASK_PROMOTEDFIELDS) != 0;
+
+ /* Set the SecurityHeader */
+#ifdef UA_ENABLE_PUBSUB_ENCRYPTION
+ if(wg->config.securityMode > UA_MESSAGESECURITYMODE_NONE) {
+ networkMessage->securityEnabled = true;
+ networkMessage->securityHeader.networkMessageSigned = true;
+ if(wg->config.securityMode >= UA_MESSAGESECURITYMODE_SIGNANDENCRYPT)
+ networkMessage->securityHeader.networkMessageEncrypted = true;
+ networkMessage->securityHeader.securityTokenId = wg->securityTokenId;
+
+ /* Generate the MessageNonce */
+ UA_ByteString_allocBuffer(&networkMessage->securityHeader.messageNonce, 8);
+ if(networkMessage->securityHeader.messageNonce.length == 0)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+
+ networkMessage->securityHeader.messageNonce.length = 4; /* Generate 4 random bytes */
+ UA_StatusCode rv = wg->config.securityPolicy->symmetricModule.
+ generateNonce(wg->config.securityPolicy->policyContext,
+ &networkMessage->securityHeader.messageNonce);
+ if(rv != UA_STATUSCODE_GOOD)
+ return rv;
+ networkMessage->securityHeader.messageNonce.length = 8;
+ UA_Byte *pos = &networkMessage->securityHeader.messageNonce.data[4];
+ const UA_Byte *end = &networkMessage->securityHeader.messageNonce.data[8];
+ UA_UInt32_encodeBinary(&wg->nonceSequenceNumber, &pos, end);
+ }
+#endif
+
networkMessage->version = 1;
networkMessage->networkMessageType = UA_NETWORKMESSAGE_DATASET;
if(connection->config->publisherIdType == UA_PUBSUB_PUBLISHERID_NUMERIC) {
networkMessage->publisherIdType = UA_PUBLISHERDATATYPE_UINT16;
- networkMessage->publisherId.publisherIdUInt32 = connection->config->publisherId.numeric;
- } else if(connection->config->publisherIdType == UA_PUBSUB_PUBLISHERID_STRING){
+ networkMessage->publisherId.publisherIdUInt32 =
+ connection->config->publisherId.numeric;
+ } else if(connection->config->publisherIdType == UA_PUBSUB_PUBLISHERID_STRING) {
networkMessage->publisherIdType = UA_PUBLISHERDATATYPE_STRING;
- networkMessage->publisherId.publisherIdString = connection->config->publisherId.string;
+ networkMessage->publisherId.publisherIdString =
+ connection->config->publisherId.string;
}
+
if(networkMessage->groupHeader.sequenceNumberEnabled)
networkMessage->groupHeader.sequenceNumber = wg->sequenceNumber;
+
+ if(networkMessage->groupHeader.groupVersionEnabled)
+ networkMessage->groupHeader.groupVersion = wgm->groupVersion;
+
/* Compute the length of the dsm separately for the header */
- UA_STACKARRAY(UA_UInt16, dsmLengths, dsmCount);
+ UA_UInt16 *dsmLengths = (UA_UInt16 *) UA_calloc(dsmCount, sizeof(UA_UInt16));
+ if(!dsmLengths)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
for(UA_Byte i = 0; i < dsmCount; i++)
dsmLengths[i] = (UA_UInt16) UA_DataSetMessage_calcSizeBinary(&dsm[i], NULL, 0);
@@ -29963,58 +30108,115 @@ generateNetworkMessage(UA_PubSubConnection *connection, UA_WriterGroup *wg,
}
static UA_StatusCode
-sendBufferedNetworkMessage(UA_Server *server, UA_PubSubConnection *connection,
- UA_NetworkMessageOffsetBuffer *buffer,
- UA_ExtensionObject *transportSettings) {
- if(UA_NetworkMessage_updateBufferedMessage(buffer) != UA_STATUSCODE_GOOD)
- UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER,
- "PubSub sending. Unknown field type.");
- return connection->channel->send(connection->channel,
- transportSettings, &buffer->buffer);
-}
-
-static UA_StatusCode
-sendNetworkMessage(UA_PubSubConnection *connection, UA_WriterGroup *wg,
- UA_DataSetMessage *dsm, UA_UInt16 *writerIds, UA_Byte dsmCount,
- UA_ExtensionObject *messageSettings,
- UA_ExtensionObject *transportSettings) {
+sendNetworkMessageBinary(UA_PubSubConnection *connection, UA_WriterGroup *wg,
+ UA_DataSetMessage *dsm, UA_UInt16 *writerIds, UA_Byte dsmCount) {
UA_NetworkMessage nm;
memset(&nm, 0, sizeof(UA_NetworkMessage));
- generateNetworkMessage(connection, wg, dsm, writerIds, dsmCount,
- messageSettings, transportSettings, &nm);
+
+ /* Fill the message structure */
+ UA_StatusCode rv =
+ generateNetworkMessage(connection, wg, dsm, writerIds, dsmCount,
+ &wg->config.messageSettings,
+ &wg->config.transportSettings, &nm);
+ UA_CHECK_STATUS(rv, return rv);
+
+ /* Compute the message size. Add the overhead for the security signature.
+ * There is no padding and the encryption incurs no size overhead. */
+ size_t msgSize = UA_NetworkMessage_calcSizeBinary(&nm, NULL);
+#ifdef UA_ENABLE_PUBSUB_ENCRYPTION
+ if(wg->config.securityMode > UA_MESSAGESECURITYMODE_NONE) {
+ UA_PubSubSecurityPolicy *sp = wg->config.securityPolicy;
+ msgSize += sp->symmetricModule.cryptoModule.
+ signatureAlgorithm.getLocalSignatureSize(sp->policyContext);
+ }
+#endif
/* Allocate the buffer. Allocate on the stack if the buffer is small. */
UA_ByteString buf;
- size_t msgSize = UA_NetworkMessage_calcSizeBinary(&nm, NULL);
- size_t stackSize = 1;
- if(msgSize <= UA_MAX_STACKBUF)
- stackSize = msgSize;
- UA_STACKARRAY(UA_Byte, stackBuf, stackSize);
+ UA_Byte stackBuf[UA_MAX_STACKBUF];
buf.data = stackBuf;
buf.length = msgSize;
- UA_StatusCode retval;
if(msgSize > UA_MAX_STACKBUF) {
- retval = UA_ByteString_allocBuffer(&buf, msgSize);
- if(retval != UA_STATUSCODE_GOOD)
- return retval;
+ rv = UA_ByteString_allocBuffer(&buf, msgSize);
+ UA_CHECK_STATUS(rv, goto cleanup);
}
- /* Encode the message */
- UA_Byte *bufPos = buf.data;
- memset(bufPos, 0, msgSize);
- const UA_Byte *bufEnd = &buf.data[buf.length];
- retval = UA_NetworkMessage_encodeBinary(&nm, &bufPos, bufEnd);
- if(retval != UA_STATUSCODE_GOOD) {
- if(msgSize > UA_MAX_STACKBUF)
- UA_ByteString_clear(&buf);
- return retval;
- }
+ /* Encode and encrypt the message */
+ rv = encodeNetworkMessage(wg, &nm, &buf);
+ UA_CHECK_STATUS(rv, goto cleanup_with_msg_size);
- /* Send the prepared messages */
- retval = connection->channel->send(connection->channel, transportSettings, &buf);
- if(msgSize > UA_MAX_STACKBUF)
+ /* Send out the message */
+ rv = connection->channel->send(connection->channel,
+ &wg->config.transportSettings, &buf);
+ UA_CHECK_STATUS(rv, goto cleanup_with_msg_size);
+
+cleanup_with_msg_size:
+ if(msgSize > UA_MAX_STACKBUF) {
UA_ByteString_clear(&buf);
- return retval;
+ }
+cleanup:
+ UA_ByteString_clear(&nm.securityHeader.messageNonce);
+ UA_free(nm.payload.dataSetPayload.sizes);
+ return rv;
+}
+
+static void
+sendNetworkMessage(UA_Server *server, UA_WriterGroup *wg, UA_PubSubConnection *connection,
+ UA_DataSetMessage *dsm, UA_UInt16 *writerIds, UA_Byte dsmCount) {
+ UA_StatusCode res = UA_STATUSCODE_GOOD;
+ switch(wg->config.encodingMimeType) {
+ case UA_PUBSUB_ENCODING_UADP:
+ res = sendNetworkMessageBinary(connection, wg, dsm, writerIds, dsmCount);
+ break;
+#ifdef UA_ENABLE_JSON_ENCODING
+ case UA_PUBSUB_ENCODING_JSON:
+ res = sendNetworkMessageJson(connection, wg, dsm, writerIds, dsmCount);
+ break;
+#endif
+ default:
+ res = UA_STATUSCODE_BADNOTSUPPORTED;
+ break;
+ }
+
+ /* If sending failed, disable all writer of the writergroup */
+ if(res != UA_STATUSCODE_GOOD) {
+ UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "PubSub Publish: Could not send a NetworkMessage "
+ "with status code %s", UA_StatusCode_name(res));
+ UA_DataSetWriter *dsw;
+ LIST_FOREACH(dsw, &wg->writers, listEntry) {
+ UA_DataSetWriter_setPubSubState(server, UA_PUBSUBSTATE_ERROR, dsw);
+ }
+ return;
+ }
+
+ /* Increase the sequence number */
+ wg->sequenceNumber++;
+}
+
+static void
+sendBufferedNetworkMessage(UA_Server *server, UA_WriterGroup *wg,
+ UA_PubSubConnection *connection) {
+ UA_NetworkMessageOffsetBuffer *buf = &wg->bufferedMessage;
+ UA_StatusCode res = UA_NetworkMessage_updateBufferedMessage(buf);
+ if(res != UA_STATUSCODE_GOOD) {
+ UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "PubSub sending failed - could not update the message");
+ UA_WriterGroup_setPubSubState(server, UA_PUBSUBSTATE_ERROR, wg);
+ return;
+ }
+
+ res = connection->channel->send(connection->channel,
+ &wg->config.transportSettings, &buf->buffer);
+ if(res != UA_STATUSCODE_GOOD) {
+ UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Publish failed. RT fixed size. sendBufferedNetworkMessage failed");
+ UA_WriterGroup_setPubSubState(server, UA_PUBSUBSTATE_ERROR, wg);
+ return;
+ }
+
+ /* Sending successful - increase the sequence number */
+ wg->sequenceNumber++;
}
/* This callback triggers the collection and publish of NetworkMessages and the
@@ -30023,38 +30225,32 @@ void
UA_WriterGroup_publishCallback(UA_Server *server, UA_WriterGroup *writerGroup) {
UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER, "Publish Callback");
+ // TODO: review if its okay to force correct value from caller side instead
+ // UA_assert(writerGroup != NULL);
+ // UA_assert(server != NULL);
+
if(!writerGroup) {
- UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
- "Publish failed. WriterGroup not found");
+ UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Publish failed. WriterGroup not found");
return;
}
/* Nothing to do? */
- if(writerGroup->writersCount <= 0)
- return;
-
- /* Binary or Json encoding? */
- if(writerGroup->config.encodingMimeType != UA_PUBSUB_ENCODING_UADP &&
- writerGroup->config.encodingMimeType != UA_PUBSUB_ENCODING_JSON) {
- UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
- "Publish failed: Unknown encoding type.");
+ if(writerGroup->writersCount == 0)
return;
- }
/* Find the connection associated with the writer */
UA_PubSubConnection *connection = writerGroup->linkedConnection;
if(!connection) {
- UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
"Publish failed. PubSubConnection invalid.");
+ UA_WriterGroup_setPubSubState(server, UA_PUBSUBSTATE_ERROR, writerGroup);
return;
}
+ /* Realtime path - update the buffer message and send directly */
if(writerGroup->config.rtLevel == UA_PUBSUB_RT_FIXED_SIZE) {
- UA_StatusCode res =
- sendBufferedNetworkMessage(server, connection, &writerGroup->bufferedMessage,
- &writerGroup->config.transportSettings);
- if(res == UA_STATUSCODE_GOOD)
- writerGroup->sequenceNumber++;
+ sendBufferedNetworkMessage(server, writerGroup, connection);
return;
}
@@ -30062,110 +30258,107 @@ UA_WriterGroup_publishCallback(UA_Server *server, UA_WriterGroup *writerGroup) {
UA_Byte maxDSM = (UA_Byte)writerGroup->config.maxEncapsulatedDataSetMessageCount;
if(writerGroup->config.maxEncapsulatedDataSetMessageCount > UA_BYTE_MAX)
maxDSM = UA_BYTE_MAX;
- /* If the maxEncapsulatedDataSetMessageCount is set to 0->1 */
+
+ /* If the maxEncapsulatedDataSetMessageCount is set to 0 -> 1 */
if(maxDSM == 0)
maxDSM = 1;
/* It is possible to put several DataSetMessages into one NetworkMessage.
- * But only if they do not contain promoted fields. NM with only DSM are
- * sent out right away. The others are kept in a buffer for "batching". */
+ * But only if they do not contain promoted fields. NM with promoted fields
+ * are sent out right away. The others are kept in a buffer for
+ * "batching". */
size_t dsmCount = 0;
- UA_DataSetWriter *dsw;
UA_STACKARRAY(UA_UInt16, dsWriterIds, writerGroup->writersCount);
UA_STACKARRAY(UA_DataSetMessage, dsmStore, writerGroup->writersCount);
+
+ UA_DataSetWriter *dsw;
LIST_FOREACH(dsw, &writerGroup->writers, listEntry) {
+ if(dsw->state != UA_PUBSUBSTATE_OPERATIONAL)
+ continue;
+
/* Find the dataset */
UA_PublishedDataSet *pds =
UA_PublishedDataSet_findPDSbyId(server, dsw->connectedDataSet);
if(!pds) {
- UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
- "PubSub Publish: PublishedDataSet not found");
+ UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "PubSub Publish: PublishedDataSet not found");
+ UA_DataSetWriter_setPubSubState(server, UA_PUBSUBSTATE_ERROR, dsw);
continue;
}
/* Generate the DSM */
+ dsWriterIds[dsmCount] = dsw->config.dataSetWriterId;
UA_StatusCode res =
UA_DataSetWriter_generateDataSetMessage(server, &dsmStore[dsmCount], dsw);
if(res != UA_STATUSCODE_GOOD) {
- UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
- "PubSub Publish: DataSetMessage creation failed");
+ UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "PubSub Publish: DataSetMessage creation failed");
+ UA_DataSetWriter_setPubSubState(server, UA_PUBSUBSTATE_ERROR, dsw);
continue;
}
- /* Send right away if there is only this DSM in a NM. If promoted fields
- * are contained in the PublishedDataSet, then this DSM must go into a
- * dedicated NM as well. */
- if(pds->promotedFieldsCount > 0 || maxDSM == 1) {
- if(writerGroup->config.encodingMimeType == UA_PUBSUB_ENCODING_UADP){
- res = sendNetworkMessage(connection, writerGroup, &dsmStore[dsmCount],
- &dsw->config.dataSetWriterId, 1,
- &writerGroup->config.messageSettings,
- &writerGroup->config.transportSettings);
- } else if(writerGroup->config.encodingMimeType == UA_PUBSUB_ENCODING_JSON) {
- res = sendNetworkMessageJson(connection, &dsmStore[dsmCount],
- &dsw->config.dataSetWriterId, 1,
- &writerGroup->config.transportSettings);
- }
-
- if(res != UA_STATUSCODE_GOOD)
- UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
- "PubSub Publish: Could not send a NetworkMessage");
+ /* There is no promoted field -> send right away */
+ if(pds->promotedFieldsCount > 0) {
+ sendNetworkMessage(server, writerGroup, connection, &dsmStore[dsmCount],
+ &dsWriterIds[dsmCount], 1);
+ /* Clean up the current store entry */
if(writerGroup->config.rtLevel == UA_PUBSUB_RT_DIRECT_VALUE_ACCESS) {
for(size_t i = 0; i < dsmStore[dsmCount].data.keyFrameData.fieldCount; ++i) {
dsmStore[dsmCount].data.keyFrameData.dataSetFields[i].value.data = NULL;
}
}
+ UA_DataSetMessage_clear(&dsmStore[dsmCount]);
- UA_DataSetMessage_free(&dsmStore[dsmCount]);
- continue;
+ continue; /* Don't increase the dsmCount, reuse the slot */
}
- dsWriterIds[dsmCount] = dsw->config.dataSetWriterId;
dsmCount++;
}
/* Send the NetworkMessages with batched DataSetMessages */
- size_t nmCount = (dsmCount / maxDSM) + ((dsmCount % maxDSM) == 0 ? 0 : 1);
- for(UA_UInt32 i = 0; i < nmCount; i++) {
- UA_Byte nmDsmCount = maxDSM;
- if(i == nmCount - 1 && (dsmCount % maxDSM))
- nmDsmCount = (UA_Byte)dsmCount % maxDSM;
- UA_StatusCode res3 = UA_STATUSCODE_GOOD;
- if(writerGroup->config.encodingMimeType == UA_PUBSUB_ENCODING_UADP){
- res3 = sendNetworkMessage(connection, writerGroup, &dsmStore[i * maxDSM],
- &dsWriterIds[i * maxDSM], nmDsmCount,
- &writerGroup->config.messageSettings,
- &writerGroup->config.transportSettings);
- } else if(writerGroup->config.encodingMimeType == UA_PUBSUB_ENCODING_JSON){
- res3 = sendNetworkMessageJson(connection, &dsmStore[i * maxDSM],
- &dsWriterIds[i * maxDSM], nmDsmCount,
- &writerGroup->config.transportSettings);
- }
-
- if(res3 != UA_STATUSCODE_GOOD) {
- UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
- "PubSub Publish: Sending a NetworkMessage failed");
- continue;
- }
+ UA_Byte nmDsmCount = 0;
+ for(size_t i = 0; i < dsmCount; i += nmDsmCount) {
+ /* How many dsm are batched in this iteration? */
+ nmDsmCount = (i + maxDSM > dsmCount) ? (UA_Byte)(dsmCount - i) : maxDSM;
- writerGroup->sequenceNumber++;
+ /* Send the batched messages */
+ sendNetworkMessage(server, writerGroup, connection, &dsmStore[i],
+ &dsWriterIds[i], nmDsmCount);
}
/* Clean up DSM */
- for(size_t i = 0; i < dsmCount; i++)
- UA_DataSetMessage_free(&dsmStore[i]);
+ for(size_t i = 0; i < dsmCount; i++) {
+ if(writerGroup->config.rtLevel == UA_PUBSUB_RT_DIRECT_VALUE_ACCESS) {
+ for(size_t j = 0; j < dsmStore[i].data.keyFrameData.fieldCount; ++j) {
+ dsmStore[i].data.keyFrameData.dataSetFields[j].value.data = NULL;
+ }
+ }
+ UA_DataSetMessage_clear(&dsmStore[i]);
+ }
}
/* Add new publishCallback. The first execution is triggered directly after
* creation. */
UA_StatusCode
UA_WriterGroup_addPublishCallback(UA_Server *server, UA_WriterGroup *writerGroup) {
- UA_StatusCode retval =
- UA_PubSubManager_addRepeatedCallback(server,
- (UA_ServerCallback) UA_WriterGroup_publishCallback,
- writerGroup, writerGroup->config.publishingInterval,
- &writerGroup->publishCallbackId);
+ UA_StatusCode retval = UA_STATUSCODE_GOOD;
+ if(writerGroup->config.pubsubManagerCallback.addCustomCallback)
+ retval |= writerGroup->config.pubsubManagerCallback.
+ addCustomCallback(server, writerGroup->identifier,
+ (UA_ServerCallback) UA_WriterGroup_publishCallback,
+ writerGroup, writerGroup->config.publishingInterval,
+ NULL, // TODO: Send base time from writer group config
+ UA_TIMER_HANDLE_CYCLEMISS_WITH_CURRENTTIME, // TODO: Send timer policy from writer group config
+ &writerGroup->publishCallbackId);
+ else
+ retval |= UA_PubSubManager_addRepeatedCallback(server,
+ (UA_ServerCallback) UA_WriterGroup_publishCallback,
+ writerGroup, writerGroup->config.publishingInterval,
+ NULL, // TODO: Send base time from writer group config
+ UA_TIMER_HANDLE_CYCLEMISS_WITH_CURRENTTIME, // TODO: Send timer policy from writer group config
+ &writerGroup->publishCallbackId);
+
if(retval == UA_STATUSCODE_GOOD)
writerGroup->publishCallbackIsRegistered = true;
@@ -30176,7 +30369,7 @@ UA_WriterGroup_addPublishCallback(UA_Server *server, UA_WriterGroup *writerGroup
#endif /* UA_ENABLE_PUBSUB */
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/src/pubsub/ua_pubsub_reader.c" ***********************************/
+/**** amalgamated original file "/src/pubsub/ua_pubsub_reader.c" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -30185,9 +30378,11 @@ UA_WriterGroup_addPublishCallback(UA_Server *server, UA_WriterGroup *writerGroup
* Copyright (c) 2017-2018 Fraunhofer IOSB (Author: Andreas Ebner)
* Copyright (c) 2019 Fraunhofer IOSB (Author: Julius Pfrommer)
* Copyright (c) 2019 Kalycito Infotech Private Limited
+ * Copyright (c) 2021 Fraunhofer IOSB (Author: Jan Hermes)
*/
+
#ifdef UA_ENABLE_PUBSUB /* conditional compilation */
@@ -30197,401 +30392,562 @@ UA_WriterGroup_addPublishCallback(UA_Server *server, UA_WriterGroup *writerGroup
#ifdef UA_ENABLE_PUBSUB_DELTAFRAMES
#endif
-#define UA_MAX_SIZENAME 64 /* Max size of Qualified Name of Subscribed Variable */
+#ifdef UA_ENABLE_PUBSUB_BUFMALLOC
+#endif
-/***************/
-/* ReaderGroup */
-/***************/
+/* This functionality of this API will be used in future to create mirror Variables - TODO */
+/* #define UA_MAX_SIZENAME 64 */ /* Max size of Qualified Name of Subscribed Variable */
-UA_StatusCode
-UA_Server_addReaderGroup(UA_Server *server, UA_NodeId connectionIdentifier,
- const UA_ReaderGroupConfig *readerGroupConfig,
- UA_NodeId *readerGroupIdentifier) {
- UA_StatusCode retval = UA_STATUSCODE_GOOD;
+/* Clear DataSetReader */
+static void
+UA_DataSetReader_clear(UA_Server *server, UA_DataSetReader *dataSetReader);
- /* Check for valid readergroup configuration */
- if(!readerGroupConfig) {
- return UA_STATUSCODE_BADINVALIDARGUMENT;
- }
+static void
+UA_PubSubDSRDataSetField_sampleValue(UA_Server *server, UA_DataSetReader *dataSetReader,
+ UA_DataValue *value, UA_FieldTargetVariable *ftv) {
+ /* TODO: Static value source without RT information model
+ * This API supports only to external datasource in RT configutation
+ * TODO: Extend to support other configuration if required */
+
+ /* Get the Node */
+ const UA_VariableNode *rtNode = (const UA_VariableNode *)
+ UA_NODESTORE_GET(server, &ftv->targetVariable.targetNodeId);
+ if(!rtNode)
+ return;
- /* Search the connection by the given connectionIdentifier */
- UA_PubSubConnection *currentConnectionContext =
- UA_PubSubConnection_findConnectionbyId(server, connectionIdentifier);
- if(!currentConnectionContext) {
- return UA_STATUSCODE_BADNOTFOUND;
+ if(rtNode->valueBackend.backendType == UA_VALUEBACKENDTYPE_EXTERNAL) {
+ /* Set the external source in the dataset reader config */
+ ftv->externalDataValue = rtNode->valueBackend.backend.external.value;
+
+ /* Get the value to compute the offsets */
+ *value = **rtNode->valueBackend.backend.external.value;
+ value->value.storageType = UA_VARIANT_DATA_NODELETE;
}
- /* Allocate memory for new reader group */
- UA_ReaderGroup *newGroup = (UA_ReaderGroup *)UA_calloc(1, sizeof(UA_ReaderGroup));
- if(!newGroup) {
+ UA_NODESTORE_RELEASE(server, (const UA_Node *) rtNode);
+}
+
+static UA_StatusCode
+UA_PubSubDataSetReader_generateKeyFrameMessage(UA_Server *server,
+ UA_DataSetMessage *dataSetMessage,
+ UA_DataSetReader *dataSetReader) {
+ /* Prepare DataSetMessageContent */
+ UA_TargetVariables *tv = &dataSetReader->config.subscribedDataSet.subscribedDataSetTarget;
+ dataSetMessage->header.dataSetMessageValid = true;
+ dataSetMessage->header.dataSetMessageType = UA_DATASETMESSAGE_DATAKEYFRAME;
+ dataSetMessage->data.keyFrameData.fieldCount = (UA_UInt16) tv->targetVariablesSize;
+ dataSetMessage->data.keyFrameData.dataSetFields = (UA_DataValue *)
+ UA_Array_new(tv->targetVariablesSize, &UA_TYPES[UA_TYPES_DATAVALUE]);
+ if(!dataSetMessage->data.keyFrameData.dataSetFields)
return UA_STATUSCODE_BADOUTOFMEMORY;
- }
- /* Generate nodeid for the readergroup identifier */
- newGroup->linkedConnection = currentConnectionContext->identifier;
- UA_PubSubManager_generateUniqueNodeId(server, &newGroup->identifier);
- if(readerGroupIdentifier) {
- UA_NodeId_copy(&newGroup->identifier, readerGroupIdentifier);
- }
+ for(size_t counter = 0; counter < tv->targetVariablesSize; counter++) {
+ /* Sample the value and set the source in the reader config */
+ UA_DataValue *dfv = &dataSetMessage->data.keyFrameData.dataSetFields[counter];
+ UA_FieldTargetVariable *ftv = &tv->targetVariables[counter];
+ UA_PubSubDSRDataSetField_sampleValue(server, dataSetReader, dfv, ftv);
- /* Deep copy of the config */
- retval |= UA_ReaderGroupConfig_copy(readerGroupConfig, &newGroup->config);
- retval |= UA_ReaderGroup_addSubscribeCallback(server, newGroup);
- LIST_INSERT_HEAD(&currentConnectionContext->readerGroups, newGroup, listEntry);
- currentConnectionContext->readerGroupsSize++;
+ /* Deactivate statuscode? */
+ if(((u64)dataSetReader->config.dataSetFieldContentMask &
+ (u64)UA_DATASETFIELDCONTENTMASK_STATUSCODE) == 0)
+ dfv->hasStatus = false;
-#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL
- addReaderGroupRepresentation(server, newGroup);
-#endif
+ /* Deactivate timestamps */
+ if(((u64)dataSetReader->config.dataSetFieldContentMask &
+ (u64)UA_DATASETFIELDCONTENTMASK_SOURCETIMESTAMP) == 0)
+ dfv->hasSourceTimestamp = false;
+ if(((u64)dataSetReader->config.dataSetFieldContentMask &
+ (u64)UA_DATASETFIELDCONTENTMASK_SOURCEPICOSECONDS) == 0)
+ dfv->hasSourcePicoseconds = false;
+ if(((u64)dataSetReader->config.dataSetFieldContentMask &
+ (u64)UA_DATASETFIELDCONTENTMASK_SERVERTIMESTAMP) == 0)
+ dfv->hasServerTimestamp = false;
+ if(((u64)dataSetReader->config.dataSetFieldContentMask &
+ (u64)UA_DATASETFIELDCONTENTMASK_SERVERPICOSECONDS) == 0)
+ dfv->hasServerPicoseconds = false;
+ }
- return retval;
+ return UA_STATUSCODE_GOOD;
}
+/* Generate a DataSetMessage for the given reader. */
UA_StatusCode
-UA_Server_removeReaderGroup(UA_Server *server, UA_NodeId groupIdentifier) {
- UA_ReaderGroup* readerGroup = UA_ReaderGroup_findRGbyId(server, groupIdentifier);
- if(readerGroup == NULL) {
- return UA_STATUSCODE_BADNOTFOUND;
+UA_DataSetReader_generateDataSetMessage(UA_Server *server,
+ UA_DataSetMessage *dataSetMessage,
+ UA_DataSetReader *dataSetReader) {
+ /* Reset the message */
+ memset(dataSetMessage, 0, sizeof(UA_DataSetMessage));
+
+ /* Support only for UADP configuration
+ * TODO: JSON encoding if UA_DataSetReader_generateDataSetMessage used other
+ * that RT configuration */
+
+ UA_ExtensionObject *settings = &dataSetReader->config.messageSettings;
+ if(settings->content.decoded.type != &UA_TYPES[UA_TYPES_UADPDATASETREADERMESSAGEDATATYPE]) {
+ UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Only UADP encoding is supported.");
+ return UA_STATUSCODE_BADNOTSUPPORTED;
}
- /* Search the connection to which the given readergroup is connected to */
- UA_PubSubConnection *connection =
- UA_PubSubConnection_findConnectionbyId(server, readerGroup->linkedConnection);
- if(connection == NULL) {
- return UA_STATUSCODE_BADNOTFOUND;
+ /* The configuration Flags are included inside the std. defined UA_UadpDataSetReaderMessageDataType */
+ UA_UadpDataSetReaderMessageDataType defaultUadpConfiguration;
+ UA_UadpDataSetReaderMessageDataType *dataSetReaderMessageDataType =
+ (UA_UadpDataSetReaderMessageDataType*) settings->content.decoded.data;
+
+ if(!(settings->encoding == UA_EXTENSIONOBJECT_DECODED ||
+ settings->encoding == UA_EXTENSIONOBJECT_DECODED_NODELETE) ||
+ !dataSetReaderMessageDataType->dataSetMessageContentMask) {
+ /* create default flag configuration if no dataSetMessageContentMask or even messageSettings in
+ * UadpDataSetWriterMessageDataType was passed in */
+ memset(&defaultUadpConfiguration, 0, sizeof(UA_UadpDataSetReaderMessageDataType));
+ defaultUadpConfiguration.dataSetMessageContentMask = (UA_UadpDataSetMessageContentMask)
+ ((u64)UA_UADPDATASETMESSAGECONTENTMASK_TIMESTAMP |
+ (u64)UA_UADPDATASETMESSAGECONTENTMASK_MAJORVERSION |
+ (u64)UA_UADPDATASETMESSAGECONTENTMASK_MINORVERSION);
+ dataSetReaderMessageDataType = &defaultUadpConfiguration;
}
- /* Unregister subscribe callback */
- UA_PubSubManager_removeRepeatedPubSubCallback(server, readerGroup->subscribeCallbackId);
-#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL
- /* To Do:RemoveGroupRepresentation(server, &readerGroup->identifier) */
-#endif
+ /* Sanity-test the configuration */
+ if(dataSetReaderMessageDataType &&
+ (dataSetReaderMessageDataType->networkMessageNumber != 0 ||
+ dataSetReaderMessageDataType->dataSetOffset != 0)) {
+ UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Static DSM configuration not supported. Using defaults");
+ dataSetReaderMessageDataType->networkMessageNumber = 0;
+ dataSetReaderMessageDataType->dataSetOffset = 0;
+ }
- /* UA_Server_ReaderGroup_delete also removes itself from the list */
- UA_Server_ReaderGroup_delete(server, readerGroup);
- /* Remove readerGroup from Connection */
- LIST_REMOVE(readerGroup, listEntry);
- UA_free(readerGroup);
- return UA_STATUSCODE_GOOD;
-}
+ /* The field encoding depends on the flags inside the reader config. */
+ if(dataSetReader->config.dataSetFieldContentMask &
+ (u64)UA_DATASETFIELDCONTENTMASK_RAWDATA) {
+ dataSetMessage->header.fieldEncoding = UA_FIELDENCODING_RAWDATA;
+ } else if((u64)dataSetReader->config.dataSetFieldContentMask &
+ ((u64)UA_DATASETFIELDCONTENTMASK_SOURCETIMESTAMP |
+ (u64)UA_DATASETFIELDCONTENTMASK_SERVERPICOSECONDS |
+ (u64)UA_DATASETFIELDCONTENTMASK_SOURCEPICOSECONDS |
+ (u64)UA_DATASETFIELDCONTENTMASK_STATUSCODE)) {
+ dataSetMessage->header.fieldEncoding = UA_FIELDENCODING_DATAVALUE;
+ } else {
+ dataSetMessage->header.fieldEncoding = UA_FIELDENCODING_VARIANT;
+ }
-/* TODO: Implement
-UA_StatusCode
-UA_Server_ReaderGroup_updateConfig(UA_Server *server, UA_NodeId readerGroupIdentifier,
- const UA_ReaderGroupConfig *config) {
- return UA_STATUSCODE_BADNOTIMPLEMENTED;
-}
-*/
+ /* Std: 'The DataSetMessageContentMask defines the flags for the content
+ * of the DataSetMessage header.' */
+ if((u64)dataSetReaderMessageDataType->dataSetMessageContentMask &
+ (u64)UA_UADPDATASETMESSAGECONTENTMASK_MAJORVERSION) {
+ dataSetMessage->header.configVersionMajorVersionEnabled = true;
+ dataSetMessage->header.configVersionMajorVersion =
+ dataSetReader->config.dataSetMetaData.configurationVersion.majorVersion;
+ }
-UA_StatusCode
-UA_Server_ReaderGroup_getConfig(UA_Server *server, UA_NodeId readerGroupIdentifier,
- UA_ReaderGroupConfig *config) {
- if(!config) {
- return UA_STATUSCODE_BADINVALIDARGUMENT;
+ if((u64)dataSetReaderMessageDataType->dataSetMessageContentMask &
+ (u64)UA_UADPDATASETMESSAGECONTENTMASK_MINORVERSION) {
+ dataSetMessage->header.configVersionMinorVersionEnabled = true;
+ dataSetMessage->header.configVersionMinorVersion =
+ dataSetReader->config.dataSetMetaData.configurationVersion.minorVersion;
}
- /* Identify the readergroup through the readerGroupIdentifier */
- UA_ReaderGroup *currentReaderGroup = UA_ReaderGroup_findRGbyId(server, readerGroupIdentifier);
- if(!currentReaderGroup) {
- return UA_STATUSCODE_BADNOTFOUND;
+ if((u64)dataSetReaderMessageDataType->dataSetMessageContentMask &
+ (u64)UA_UADPDATASETMESSAGECONTENTMASK_SEQUENCENUMBER) {
+ /* Will be modified when subscriber receives new nw msg */
+ dataSetMessage->header.dataSetMessageSequenceNrEnabled = true;
+ dataSetMessage->header.dataSetMessageSequenceNr = 1;
}
- UA_ReaderGroupConfig tmpReaderGroupConfig;
- /* deep copy of the actual config */
- UA_ReaderGroupConfig_copy(&currentReaderGroup->config, &tmpReaderGroupConfig);
- *config = tmpReaderGroupConfig;
- return UA_STATUSCODE_GOOD;
-}
+ if((u64)dataSetReaderMessageDataType->dataSetMessageContentMask &
+ (u64)UA_UADPDATASETMESSAGECONTENTMASK_TIMESTAMP) {
+ dataSetMessage->header.timestampEnabled = true;
+ dataSetMessage->header.timestamp = UA_DateTime_now();
+ }
-void
-UA_Server_ReaderGroup_delete(UA_Server* server, UA_ReaderGroup *readerGroup) {
- /* To Do Call UA_ReaderGroupConfig_delete */
- UA_DataSetReader *dataSetReader, *tmpDataSetReader;
- LIST_FOREACH_SAFE(dataSetReader, &readerGroup->readers, listEntry, tmpDataSetReader) {
- UA_DataSetReader_delete(server, dataSetReader);
+ /* TODO: Picoseconds resolution not supported atm */
+ if((u64)dataSetReaderMessageDataType->dataSetMessageContentMask &
+ (u64)UA_UADPDATASETMESSAGECONTENTMASK_PICOSECONDS) {
+ dataSetMessage->header.picoSecondsIncluded = false;
}
- UA_PubSubConnection* pConn =
- UA_PubSubConnection_findConnectionbyId(server, readerGroup->linkedConnection);
- if(pConn != NULL) {
- pConn->readerGroupsSize--;
+
+ if((u64)dataSetReaderMessageDataType->dataSetMessageContentMask &
+ (u64)UA_UADPDATASETMESSAGECONTENTMASK_STATUS) {
+ dataSetMessage->header.statusEnabled = true;
}
- /* Delete ReaderGroup and its members */
- UA_String_deleteMembers(&readerGroup->config.name);
- UA_NodeId_deleteMembers(&readerGroup->linkedConnection);
- UA_NodeId_deleteMembers(&readerGroup->identifier);
+ /* Not supported for Delta frames atm */
+ return UA_PubSubDataSetReader_generateKeyFrameMessage(server, dataSetMessage, dataSetReader);
}
UA_StatusCode
-UA_ReaderGroupConfig_copy(const UA_ReaderGroupConfig *src,
- UA_ReaderGroupConfig *dst) {
- /* Currently simple memcpy only */
- memcpy(&dst->securityParameters, &src->securityParameters, sizeof(UA_PubSubSecurityParameters));
- UA_String_copy(&src->name, &dst->name);
- return UA_STATUSCODE_GOOD;
-}
+UA_DataSetReader_generateNetworkMessage(UA_PubSubConnection *pubSubConnection,
+ UA_DataSetReader *dataSetReader,
+ UA_DataSetMessage *dsm, UA_UInt16 *writerId,
+ UA_Byte dsmCount, UA_NetworkMessage *nm) {
+ UA_ExtensionObject *settings = &dataSetReader->config.messageSettings;
+ if(settings->content.decoded.type != &UA_TYPES[UA_TYPES_UADPDATASETREADERMESSAGEDATATYPE])
+ return UA_STATUSCODE_BADNOTSUPPORTED;
-static UA_StatusCode
-checkReaderIdentifier(UA_Server *server, UA_NetworkMessage *pMsg, UA_DataSetReader *reader) {
- if(!pMsg->groupHeaderEnabled &&
- !pMsg->groupHeader.writerGroupIdEnabled &&
- !pMsg->payloadHeaderEnabled) {
- UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_SERVER,
- "Cannot process DataSetReader without WriterGroup"
- "and DataSetWriter identifiers");
- return UA_STATUSCODE_BADNOTIMPLEMENTED;
- }
+ UA_UadpDataSetReaderMessageDataType *dsrm =
+ (UA_UadpDataSetReaderMessageDataType*)settings->content.decoded.data;
+ nm->publisherIdEnabled = ((u64)dsrm->networkMessageContentMask &
+ (u64)UA_UADPNETWORKMESSAGECONTENTMASK_PUBLISHERID) != 0;
+ nm->groupHeaderEnabled = ((u64)dsrm->networkMessageContentMask &
+ (u64)UA_UADPNETWORKMESSAGECONTENTMASK_GROUPHEADER) != 0;
+ nm->groupHeader.writerGroupIdEnabled = ((u64)dsrm->networkMessageContentMask &
+ (u64)UA_UADPNETWORKMESSAGECONTENTMASK_WRITERGROUPID) != 0;
+ nm->groupHeader.groupVersionEnabled = ((u64)dsrm->networkMessageContentMask &
+ (u64)UA_UADPNETWORKMESSAGECONTENTMASK_GROUPVERSION) != 0;
+ nm->groupHeader.networkMessageNumberEnabled = ((u64)dsrm->networkMessageContentMask &
+ (u64)UA_UADPNETWORKMESSAGECONTENTMASK_NETWORKMESSAGENUMBER) != 0;
+ nm->groupHeader.sequenceNumberEnabled = ((u64)dsrm->networkMessageContentMask &
+ (u64)UA_UADPNETWORKMESSAGECONTENTMASK_SEQUENCENUMBER) != 0;
+ nm->payloadHeaderEnabled = ((u64)dsrm->networkMessageContentMask &
+ (u64)UA_UADPNETWORKMESSAGECONTENTMASK_PAYLOADHEADER) != 0;
+ nm->timestampEnabled = ((u64)dsrm->networkMessageContentMask &
+ (u64)UA_UADPNETWORKMESSAGECONTENTMASK_TIMESTAMP) != 0;
+ nm->picosecondsEnabled = ((u64)dsrm->networkMessageContentMask &
+ (u64)UA_UADPNETWORKMESSAGECONTENTMASK_PICOSECONDS) != 0;
+ nm->dataSetClassIdEnabled = ((u64)dsrm->networkMessageContentMask &
+ (u64)UA_UADPNETWORKMESSAGECONTENTMASK_DATASETCLASSID) != 0;
+ nm->promotedFieldsEnabled = ((u64)dsrm->networkMessageContentMask &
+ (u64)UA_UADPNETWORKMESSAGECONTENTMASK_PROMOTEDFIELDS) != 0;
+ nm->version = 1;
+ nm->networkMessageType = UA_NETWORKMESSAGE_DATASET;
+
+ if(!UA_DataType_isNumeric(dataSetReader->config.publisherId.type))
+ return UA_STATUSCODE_BADNOTSUPPORTED;
- if((reader->config.writerGroupId == pMsg->groupHeader.writerGroupId) &&
- (reader->config.dataSetWriterId == *pMsg->payloadHeader.dataSetPayloadHeader.dataSetWriterIds)) {
- UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER,
- "DataSetReader found. Process NetworkMessage");
- return UA_STATUSCODE_GOOD;
+ switch(dataSetReader->config.publisherId.type->typeKind) {
+ case UA_DATATYPEKIND_BYTE:
+ nm->publisherIdType = UA_PUBLISHERDATATYPE_BYTE;
+ nm->publisherId.publisherIdByte = *(UA_Byte *) dataSetReader->config.publisherId.data;
+ break;
+ case UA_DATATYPEKIND_UINT16:
+ nm->publisherIdType = UA_PUBLISHERDATATYPE_UINT16;
+ nm->publisherId.publisherIdUInt16 = *(UA_UInt16 *) dataSetReader->config.publisherId.data;
+ break;
+ case UA_DATATYPEKIND_UINT32:
+ nm->publisherIdType = UA_PUBLISHERDATATYPE_UINT32;
+ nm->publisherId.publisherIdUInt32 = *(UA_UInt32 *) dataSetReader->config.publisherId.data;
+ break;
+ case UA_DATATYPEKIND_UINT64:
+ nm->publisherIdType = UA_PUBLISHERDATATYPE_UINT64;
+ nm->publisherId.publisherIdUInt64 = *(UA_UInt64 *) dataSetReader->config.publisherId.data;
+ break;
+ default:
+ return UA_STATUSCODE_BADNOTSUPPORTED;
}
- return UA_STATUSCODE_BADNOTFOUND;
-}
+ if(nm->groupHeader.sequenceNumberEnabled)
+ nm->groupHeader.sequenceNumber = 1; /* Will be modified when subscriber receives new nw msg. */
-static UA_StatusCode
-getReaderFromIdentifier(UA_Server *server, UA_NetworkMessage *pMsg,
- UA_DataSetReader **dataSetReader, UA_PubSubConnection *pConnection) {
- UA_StatusCode retval = UA_STATUSCODE_BADNOTFOUND;
- if(!pMsg->publisherIdEnabled) {
- UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_SERVER,
- "Cannot process DataSetReader without PublisherId");
- return UA_STATUSCODE_BADNOTIMPLEMENTED; /* TODO: Handle DSR without PublisherId */
- }
+ if(nm->groupHeader.groupVersionEnabled)
+ nm->groupHeader.groupVersion = dsrm->groupVersion;
- UA_ReaderGroup* readerGroup;
- LIST_FOREACH(readerGroup, &pConnection->readerGroups, listEntry) {
- UA_DataSetReader *tmpReader;
- LIST_FOREACH(tmpReader, &readerGroup->readers, listEntry) {
- switch (pMsg->publisherIdType) {
- case UA_PUBLISHERDATATYPE_BYTE:
- if(tmpReader->config.publisherId.type == &UA_TYPES[UA_TYPES_BYTE] &&
- pMsg->publisherIdType == UA_PUBLISHERDATATYPE_BYTE &&
- pMsg->publisherId.publisherIdByte == *(UA_Byte*)tmpReader->config.publisherId.data) {
- retval = checkReaderIdentifier(server, pMsg, tmpReader);
- }
- break;
- case UA_PUBLISHERDATATYPE_UINT16:
- if(tmpReader->config.publisherId.type == &UA_TYPES[UA_TYPES_UINT16] &&
- pMsg->publisherIdType == UA_PUBLISHERDATATYPE_UINT16 &&
- pMsg->publisherId.publisherIdUInt16 == *(UA_UInt16*) tmpReader->config.publisherId.data) {
- retval = checkReaderIdentifier(server, pMsg, tmpReader);
- }
+ /* Compute the length of the dsm separately for the header */
+ UA_UInt16 *dsmLengths = (UA_UInt16 *) UA_calloc(dsmCount, sizeof(UA_UInt16));
+ if(!dsmLengths)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ for(UA_Byte i = 0; i < dsmCount; i++){
+ dsmLengths[i] = (UA_UInt16) UA_DataSetMessage_calcSizeBinary(&dsm[i], NULL, 0);
+ switch(dataSetReader->config.expectedEncoding) {
+ case UA_PUBSUB_RT_UNKNOWN:
break;
- case UA_PUBLISHERDATATYPE_UINT32:
- if(tmpReader->config.publisherId.type == &UA_TYPES[UA_TYPES_UINT32] &&
- pMsg->publisherIdType == UA_PUBLISHERDATATYPE_UINT32 &&
- pMsg->publisherId.publisherIdUInt32 == *(UA_UInt32*)tmpReader->config.publisherId.data) {
- retval = checkReaderIdentifier(server, pMsg, tmpReader);
- }
+ case UA_PUBSUB_RT_VARIANT:
+ dsm[i].header.fieldEncoding = UA_FIELDENCODING_VARIANT;
break;
- case UA_PUBLISHERDATATYPE_UINT64:
- if(tmpReader->config.publisherId.type == &UA_TYPES[UA_TYPES_UINT64] &&
- pMsg->publisherIdType == UA_PUBLISHERDATATYPE_UINT64 &&
- pMsg->publisherId.publisherIdUInt64 == *(UA_UInt64*)tmpReader->config.publisherId.data) {
- retval = checkReaderIdentifier(server, pMsg, tmpReader);
- }
+ case UA_PUBSUB_RT_DATA_VALUE:
+ dsm[i].header.fieldEncoding = UA_FIELDENCODING_DATAVALUE;
break;
- case UA_PUBLISHERDATATYPE_STRING:
- if(tmpReader->config.publisherId.type == &UA_TYPES[UA_TYPES_STRING] &&
- pMsg->publisherIdType == UA_PUBLISHERDATATYPE_STRING &&
- UA_String_equal(&pMsg->publisherId.publisherIdString,
- (UA_String*)tmpReader->config.publisherId.data)) {
- retval = checkReaderIdentifier(server, pMsg, tmpReader);
- }
+ case UA_PUBSUB_RT_RAW:
+ dsm[i].header.fieldEncoding = UA_FIELDENCODING_RAWDATA;
break;
- default:
- return UA_STATUSCODE_BADINTERNALERROR;
- }
-
- if(retval == UA_STATUSCODE_GOOD) {
- *dataSetReader = tmpReader;
- return UA_STATUSCODE_GOOD;
- }
}
}
-
- UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_SERVER,
- "Dataset reader not found. Check PublisherID, WriterGroupID and DatasetWriterID");
- return UA_STATUSCODE_BADNOTFOUND;
-}
-
-UA_ReaderGroup *
-UA_ReaderGroup_findRGbyId(UA_Server *server, UA_NodeId identifier) {
- UA_PubSubConnection *pubSubConnection;
- TAILQ_FOREACH(pubSubConnection, &server->pubSubManager.connections, listEntry){
- UA_ReaderGroup* readerGroup = NULL;
- LIST_FOREACH(readerGroup, &pubSubConnection->readerGroups, listEntry) {
- if(UA_NodeId_equal(&identifier, &readerGroup->identifier)) {
- return readerGroup;
- }
-
- }
- }
- return NULL;
-}
-
-UA_DataSetReader *UA_ReaderGroup_findDSRbyId(UA_Server *server, UA_NodeId identifier) {
- UA_PubSubConnection *pubSubConnection;
- TAILQ_FOREACH(pubSubConnection, &server->pubSubManager.connections, listEntry){
- UA_ReaderGroup* readerGroup = NULL;
- LIST_FOREACH(readerGroup, &pubSubConnection->readerGroups, listEntry) {
- UA_DataSetReader *tmpReader;
- LIST_FOREACH(tmpReader, &readerGroup->readers, listEntry) {
- if(UA_NodeId_equal(&tmpReader->identifier, &identifier)) {
- return tmpReader;
- }
- }
- }
- }
- return NULL;
+ nm->payloadHeader.dataSetPayloadHeader.count = dsmCount;
+ nm->payloadHeader.dataSetPayloadHeader.dataSetWriterIds = writerId;
+ nm->groupHeader.writerGroupId = dataSetReader->config.writerGroupId;
+ nm->groupHeader.networkMessageNumber = 1; /* number of the NetworkMessage inside a PublishingInterval */
+ nm->payload.dataSetPayload.sizes = dsmLengths;
+ nm->payload.dataSetPayload.dataSetMessages = dsm;
+ return UA_STATUSCODE_GOOD;
}
-/* This callback triggers the collection and reception of NetworkMessages and the
- * contained DataSetMessages. */
-void UA_ReaderGroup_subscribeCallback(UA_Server *server, UA_ReaderGroup *readerGroup) {
- UA_PubSubConnection *connection =
- UA_PubSubConnection_findConnectionbyId(server, readerGroup->linkedConnection);
- UA_ByteString buffer;
- if(UA_ByteString_allocBuffer(&buffer, 512) != UA_STATUSCODE_GOOD) {
- UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_SERVER, "Message buffer alloc failed!");
- return;
+static UA_StatusCode
+checkReaderIdentifier(UA_Server *server, UA_NetworkMessage *msg,
+ UA_DataSetReader *reader) {
+ if(!msg->groupHeaderEnabled || !msg->groupHeader.writerGroupIdEnabled ||
+ !msg->payloadHeaderEnabled) {
+ UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Cannot process DataSetReader without WriterGroup"
+ "and DataSetWriter identifiers");
+ return UA_STATUSCODE_BADNOTIMPLEMENTED;
}
- connection->channel->receive(connection->channel, &buffer, NULL, 1000);
- if(buffer.length > 0) {
- UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_USERLAND, "Message received:");
- UA_NetworkMessage currentNetworkMessage;
- memset(&currentNetworkMessage, 0, sizeof(UA_NetworkMessage));
- size_t currentPosition = 0;
- UA_NetworkMessage_decodeBinary(&buffer, &currentPosition, &currentNetworkMessage);
- UA_Server_processNetworkMessage(server, &currentNetworkMessage, connection);
- UA_NetworkMessage_deleteMembers(&currentNetworkMessage);
+ switch(msg->publisherIdType) {
+ case UA_PUBLISHERDATATYPE_BYTE:
+ if(reader->config.publisherId.type == &UA_TYPES[UA_TYPES_BYTE] &&
+ msg->publisherIdType == UA_PUBLISHERDATATYPE_BYTE &&
+ msg->publisherId.publisherIdByte == *(UA_Byte*)reader->config.publisherId.data)
+ break;
+ return UA_STATUSCODE_BADNOTFOUND;
+ case UA_PUBLISHERDATATYPE_UINT16:
+ if(reader->config.publisherId.type == &UA_TYPES[UA_TYPES_UINT16] &&
+ msg->publisherIdType == UA_PUBLISHERDATATYPE_UINT16 &&
+ msg->publisherId.publisherIdUInt16 == *(UA_UInt16*)reader->config.publisherId.data)
+ break;
+ return UA_STATUSCODE_BADNOTFOUND;
+ case UA_PUBLISHERDATATYPE_UINT32:
+ if(reader->config.publisherId.type == &UA_TYPES[UA_TYPES_UINT32] &&
+ msg->publisherIdType == UA_PUBLISHERDATATYPE_UINT32 &&
+ msg->publisherId.publisherIdUInt32 == *(UA_UInt32*)reader->config.publisherId.data)
+ break;
+ return UA_STATUSCODE_BADNOTFOUND;
+ case UA_PUBLISHERDATATYPE_UINT64:
+ if(reader->config.publisherId.type == &UA_TYPES[UA_TYPES_UINT64] &&
+ msg->publisherIdType == UA_PUBLISHERDATATYPE_UINT64 &&
+ msg->publisherId.publisherIdUInt64 == *(UA_UInt64*)reader->config.publisherId.data)
+ break;
+ return UA_STATUSCODE_BADNOTFOUND;
+ case UA_PUBLISHERDATATYPE_STRING:
+ if(reader->config.publisherId.type == &UA_TYPES[UA_TYPES_STRING] &&
+ msg->publisherIdType == UA_PUBLISHERDATATYPE_STRING &&
+ UA_String_equal(&msg->publisherId.publisherIdString,
+ (UA_String*)reader->config.publisherId.data))
+ break;
+ return UA_STATUSCODE_BADNOTFOUND;
+ default:
+ return UA_STATUSCODE_BADNOTFOUND;
}
- UA_ByteString_deleteMembers(&buffer);
-}
-
-/* Add new subscribeCallback. The first execution is triggered directly after
- * creation. */
-UA_StatusCode
-UA_ReaderGroup_addSubscribeCallback(UA_Server *server, UA_ReaderGroup *readerGroup) {
- UA_StatusCode retval = UA_STATUSCODE_GOOD;
- retval |= UA_PubSubManager_addRepeatedCallback(server,
- (UA_ServerCallback) UA_ReaderGroup_subscribeCallback,
- readerGroup, 5, &readerGroup->subscribeCallbackId);
-
- if(retval == UA_STATUSCODE_GOOD) {
- readerGroup->subscribeCallbackIsRegistered = true;
+ if(reader->config.writerGroupId == msg->groupHeader.writerGroupId &&
+ reader->config.dataSetWriterId == *msg->payloadHeader.dataSetPayloadHeader.dataSetWriterIds) {
+ UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "DataSetReader found. Process NetworkMessage");
+ return UA_STATUSCODE_GOOD;
}
- /* Run once after creation */
- UA_ReaderGroup_subscribeCallback(server, readerGroup);
- return retval;
+ return UA_STATUSCODE_BADNOTFOUND;
}
-/**********/
-/* Reader */
-/**********/
-
UA_StatusCode
UA_Server_addDataSetReader(UA_Server *server, UA_NodeId readerGroupIdentifier,
- const UA_DataSetReaderConfig *dataSetReaderConfig,
- UA_NodeId *readerIdentifier) {
+ const UA_DataSetReaderConfig *dataSetReaderConfig,
+ UA_NodeId *readerIdentifier) {
/* Search the reader group by the given readerGroupIdentifier */
UA_ReaderGroup *readerGroup = UA_ReaderGroup_findRGbyId(server, readerGroupIdentifier);
-
- if(!dataSetReaderConfig) {
+ if(readerGroup == NULL)
return UA_STATUSCODE_BADNOTFOUND;
- }
- if(readerGroup == NULL) {
+ if(!dataSetReaderConfig)
return UA_STATUSCODE_BADNOTFOUND;
+
+ if(readerGroup->configurationFrozen){
+ UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Add DataSetReader failed. Subscriber configuration is frozen.");
+ return UA_STATUSCODE_BADCONFIGURATIONERROR;
}
/* Allocate memory for new DataSetReader */
- UA_DataSetReader *newDataSetReader = (UA_DataSetReader *)UA_calloc(1, sizeof(UA_DataSetReader));
+ UA_DataSetReader *newDataSetReader = (UA_DataSetReader *)
+ UA_calloc(1, sizeof(UA_DataSetReader));
+ if(!newDataSetReader)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+
+ UA_StatusCode retVal = UA_STATUSCODE_GOOD;
+ newDataSetReader->componentType = UA_PUBSUB_COMPONENT_DATASETREADER;
+ if(readerGroup->state == UA_PUBSUBSTATE_OPERATIONAL) {
+ retVal = UA_DataSetReader_setPubSubState(server, UA_PUBSUBSTATE_OPERATIONAL, newDataSetReader);
+ if(retVal != UA_STATUSCODE_GOOD) {
+ UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Add DataSetReader failed. setPubSubState failed.");
+ UA_free(newDataSetReader);
+ newDataSetReader = 0;
+ return retVal;
+ }
+ }
+
/* Copy the config into the new dataSetReader */
UA_DataSetReaderConfig_copy(dataSetReaderConfig, &newDataSetReader->config);
newDataSetReader->linkedReaderGroup = readerGroup->identifier;
- UA_PubSubManager_generateUniqueNodeId(server, &newDataSetReader->identifier);
- if(readerIdentifier != NULL) {
- UA_NodeId_copy(&newDataSetReader->identifier, readerIdentifier);
+
+#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL
+ retVal = addDataSetReaderRepresentation(server, newDataSetReader);
+ if(retVal != UA_STATUSCODE_GOOD) {
+ UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Add DataSetReader failed. addDataSetReaderRepresentation failed.");
+ UA_DataSetReaderConfig_clear(&newDataSetReader->config);
+ UA_free(newDataSetReader);
+ newDataSetReader = 0;
+ return retVal;
}
+#else
+ UA_PubSubManager_generateUniqueNodeId(&server->pubSubManager,
+ &newDataSetReader->identifier);
+#endif
+
+#ifdef UA_ENABLE_PUBSUB_MONITORING
+ /* create message receive timeout timer */
+ retVal = server->config.pubSubConfig.monitoringInterface.createMonitoring(
+ server,
+ newDataSetReader->identifier,
+ UA_PUBSUB_COMPONENT_DATASETREADER,
+ UA_PUBSUB_MONITORING_MESSAGE_RECEIVE_TIMEOUT,
+ newDataSetReader,
+ UA_DataSetReader_handleMessageReceiveTimeout);
+ if(retVal != UA_STATUSCODE_GOOD) {
+ UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Add DataSetReader failed. Create message receive timeout timer failed.");
+ UA_DataSetReaderConfig_clear(&newDataSetReader->config);
+ UA_free(newDataSetReader);
+ newDataSetReader = 0;
+ return retVal;
+ }
+#endif /* UA_ENABLE_PUBSUB_MONITORING */
/* Add the new reader to the group */
LIST_INSERT_HEAD(&readerGroup->readers, newDataSetReader, listEntry);
readerGroup->readersCount++;
-#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL
- addDataSetReaderRepresentation(server, newDataSetReader);
-#endif
+ if(readerIdentifier)
+ UA_NodeId_copy(&newDataSetReader->identifier, readerIdentifier);
- return UA_STATUSCODE_GOOD;
+ return retVal;
}
UA_StatusCode
UA_Server_removeDataSetReader(UA_Server *server, UA_NodeId readerIdentifier) {
/* Remove datasetreader given by the identifier */
- UA_DataSetReader *dataSetReader = UA_ReaderGroup_findDSRbyId(server, readerIdentifier);
- if(!dataSetReader) {
+ UA_DataSetReader *dsr = UA_ReaderGroup_findDSRbyId(server, readerIdentifier);
+ if(!dsr)
return UA_STATUSCODE_BADNOTFOUND;
+
+ if(dsr->configurationFrozen) {
+ UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Remove DataSetReader failed. "
+ "Subscriber configuration is frozen.");
+ return UA_STATUSCODE_BADCONFIGURATIONERROR;
}
#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL
- removeDataSetReaderRepresentation(server, dataSetReader);
+ removeDataSetReaderRepresentation(server, dsr);
#endif
- UA_DataSetReader_delete(server, dataSetReader);
- return UA_STATUSCODE_GOOD;
+ UA_StatusCode res = UA_STATUSCODE_GOOD;
+#ifdef UA_ENABLE_PUBSUB_MONITORING
+ /* Stop and remove message receive timeout timer */
+ if(dsr->msgRcvTimeoutTimerRunning) {
+ res = server->config.pubSubConfig.monitoringInterface.
+ stopMonitoring(server, dsr->identifier, UA_PUBSUB_COMPONENT_DATASETREADER,
+ UA_PUBSUB_MONITORING_MESSAGE_RECEIVE_TIMEOUT, dsr);
+ if(res != UA_STATUSCODE_GOOD) {
+ UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Remove DataSetReader failed. Stop message "
+ "receive timeout timer of DataSetReader '%.*s' failed.",
+ (int) dsr->config.name.length, dsr->config.name.data);
+ }
+ }
+
+ res |= server->config.pubSubConfig.monitoringInterface.
+ deleteMonitoring(server, dsr->identifier, UA_PUBSUB_COMPONENT_DATASETREADER,
+ UA_PUBSUB_MONITORING_MESSAGE_RECEIVE_TIMEOUT, dsr);
+ if(res != UA_STATUSCODE_GOOD) {
+ UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Remove DataSetReader failed. Delete message receive "
+ "timeout timer of DataSetReader '%.*s' failed.",
+ (int) dsr->config.name.length, dsr->config.name.data);
+ }
+#endif /* UA_ENABLE_PUBSUB_MONITORING */
+
+ UA_DataSetReader_clear(server, dsr);
+ return res;
}
UA_StatusCode
UA_Server_DataSetReader_updateConfig(UA_Server *server, UA_NodeId dataSetReaderIdentifier,
UA_NodeId readerGroupIdentifier,
const UA_DataSetReaderConfig *config) {
- if(config == NULL) {
+ if(config == NULL)
return UA_STATUSCODE_BADINVALIDARGUMENT;
- }
UA_DataSetReader *currentDataSetReader =
UA_ReaderGroup_findDSRbyId(server, dataSetReaderIdentifier);
+ if(!currentDataSetReader)
+ return UA_STATUSCODE_BADNOTFOUND;
+
+ if(currentDataSetReader->configurationFrozen){
+ UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Update DataSetReader config failed. "
+ "Subscriber configuration is frozen.");
+ return UA_STATUSCODE_BADCONFIGURATIONERROR;
+ }
+
UA_ReaderGroup *currentReaderGroup =
UA_ReaderGroup_findRGbyId(server, readerGroupIdentifier);
- if(!currentDataSetReader) {
- return UA_STATUSCODE_BADNOTFOUND;
+ if(currentReaderGroup->configurationFrozen) {
+ UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Update DataSetReader config failed. "
+ "Subscriber configuration is frozen.");
+ return UA_STATUSCODE_BADCONFIGURATIONERROR;
}
/* The update functionality will be extended during the next PubSub batches.
- * Currently is only a change of the publishing interval possible. */
- if(currentDataSetReader->config.writerGroupId != config->writerGroupId) {
- UA_PubSubManager_removeRepeatedPubSubCallback(server, currentReaderGroup->subscribeCallbackId);
- currentDataSetReader->config.writerGroupId = config->writerGroupId;
- UA_ReaderGroup_subscribeCallback(server, currentReaderGroup);
- }
- else {
+ * Currently changes for writerGroupId, dataSetWriterId and TargetVariables are possible. */
+ if(currentDataSetReader->config.writerGroupId != config->writerGroupId)
+ currentDataSetReader->config.writerGroupId = config->writerGroupId;
+
+ if(currentDataSetReader->config.dataSetWriterId != config->dataSetWriterId)
+ currentDataSetReader->config.dataSetWriterId = config->dataSetWriterId;
+
+ if(currentDataSetReader->config.subscribedDataSetType != UA_PUBSUB_SDS_TARGET) {
UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
- "No or unsupported ReaderGroup update.");
+ "Unsupported SubscribedDataSetType.");
+ return UA_STATUSCODE_BADCONFIGURATIONERROR;
}
- return UA_STATUSCODE_GOOD;
+ UA_TargetVariables *oldTV =
+ &currentDataSetReader->config.subscribedDataSet.subscribedDataSetTarget;
+ const UA_TargetVariables *newTV =
+ &config->subscribedDataSet.subscribedDataSetTarget;
+ if(oldTV->targetVariablesSize == newTV->targetVariablesSize) {
+ for(size_t i = 0; i < config->subscribedDataSet.subscribedDataSetTarget.targetVariablesSize; i++) {
+ if(!UA_NodeId_equal(&oldTV->targetVariables[i].targetVariable.targetNodeId,
+ &newTV->targetVariables[i].targetVariable.targetNodeId)) {
+ UA_Server_DataSetReader_createTargetVariables(server, currentDataSetReader->identifier,
+ newTV->targetVariablesSize, newTV->targetVariables);
+ }
+ }
+ } else {
+ UA_Server_DataSetReader_createTargetVariables(server, currentDataSetReader->identifier,
+ newTV->targetVariablesSize, newTV->targetVariables);
+ }
+
+ UA_StatusCode res = UA_STATUSCODE_GOOD;
+#ifdef UA_ENABLE_PUBSUB_MONITORING
+ if(currentDataSetReader->config.messageReceiveTimeout != config->messageReceiveTimeout) {
+ /* Update message receive timeout timer interval */
+ currentDataSetReader->config.messageReceiveTimeout = config->messageReceiveTimeout;
+ res = server->config.pubSubConfig.monitoringInterface.
+ updateMonitoringInterval(server, currentDataSetReader->identifier,
+ UA_PUBSUB_COMPONENT_DATASETREADER,
+ UA_PUBSUB_MONITORING_MESSAGE_RECEIVE_TIMEOUT,
+ currentDataSetReader);
+ if(res != UA_STATUSCODE_GOOD) {
+ UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Update DataSetReader message receive timeout timer failed.");
+ }
+ }
+#endif /* UA_ENABLE_PUBSUB_MONITORING */
+ return res;
}
UA_StatusCode
UA_Server_DataSetReader_getConfig(UA_Server *server, UA_NodeId dataSetReaderIdentifier,
UA_DataSetReaderConfig *config) {
- if(!config) {
+ if(!config)
return UA_STATUSCODE_BADINVALIDARGUMENT;
- }
UA_DataSetReader *currentDataSetReader =
UA_ReaderGroup_findDSRbyId(server, dataSetReaderIdentifier);
- if(!currentDataSetReader) {
+ if(!currentDataSetReader)
return UA_STATUSCODE_BADNOTFOUND;
- }
UA_DataSetReaderConfig tmpReaderConfig;
/* Deep copy of the actual config */
@@ -30605,72 +30961,193 @@ UA_DataSetReaderConfig_copy(const UA_DataSetReaderConfig *src,
UA_DataSetReaderConfig *dst) {
memset(dst, 0, sizeof(UA_DataSetReaderConfig));
UA_StatusCode retVal = UA_String_copy(&src->name, &dst->name);
- if(retVal != UA_STATUSCODE_GOOD) {
+ if(retVal != UA_STATUSCODE_GOOD)
return retVal;
- }
retVal = UA_Variant_copy(&src->publisherId, &dst->publisherId);
- if(retVal != UA_STATUSCODE_GOOD) {
+ if(retVal != UA_STATUSCODE_GOOD)
return retVal;
- }
dst->writerGroupId = src->writerGroupId;
dst->dataSetWriterId = src->dataSetWriterId;
+ dst->expectedEncoding = src->expectedEncoding;
retVal = UA_DataSetMetaDataType_copy(&src->dataSetMetaData, &dst->dataSetMetaData);
- if(retVal != UA_STATUSCODE_GOOD) {
+ if(retVal != UA_STATUSCODE_GOOD)
return retVal;
- }
dst->dataSetFieldContentMask = src->dataSetFieldContentMask;
dst->messageReceiveTimeout = src->messageReceiveTimeout;
/* Currently memcpy is used to copy the securityParameters */
memcpy(&dst->securityParameters, &src->securityParameters, sizeof(UA_PubSubSecurityParameters));
- retVal = UA_UadpDataSetReaderMessageDataType_copy(&src->messageSettings, &dst->messageSettings);
- if(retVal != UA_STATUSCODE_GOOD) {
+ retVal = UA_ExtensionObject_copy(&src->messageSettings, &dst->messageSettings);
+ if(retVal != UA_STATUSCODE_GOOD)
return retVal;
- }
retVal = UA_ExtensionObject_copy(&src->transportSettings, &dst->transportSettings);
- if (retVal != UA_STATUSCODE_GOOD) {
- return retVal;
+ if(retVal != UA_STATUSCODE_GOOD)
+ return retVal;
+
+ if(src->subscribedDataSetType == UA_PUBSUB_SDS_TARGET) {
+ retVal = UA_TargetVariables_copy(&src->subscribedDataSet.subscribedDataSetTarget,
+ &dst->subscribedDataSet.subscribedDataSetTarget);
+ }
+ return retVal;
+}
+
+void
+UA_DataSetReaderConfig_clear(UA_DataSetReaderConfig *cfg) {
+ UA_String_clear(&cfg->name);
+ UA_Variant_clear(&cfg->publisherId);
+ UA_DataSetMetaDataType_clear(&cfg->dataSetMetaData);
+ UA_ExtensionObject_clear(&cfg->messageSettings);
+ UA_ExtensionObject_clear(&cfg->transportSettings);
+ if(cfg->subscribedDataSetType == UA_PUBSUB_SDS_TARGET) {
+ UA_TargetVariables_clear(&cfg->subscribedDataSet.subscribedDataSetTarget);
+ }
+}
+
+UA_StatusCode
+UA_Server_DataSetReader_getState(UA_Server *server, UA_NodeId dataSetReaderIdentifier,
+ UA_PubSubState *state) {
+
+ if((server == NULL) || (state == NULL))
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+ UA_DataSetReader *currentDataSetReader =
+ UA_ReaderGroup_findDSRbyId(server, dataSetReaderIdentifier);
+ if(currentDataSetReader == NULL)
+ return UA_STATUSCODE_BADNOTFOUND;
+ *state = currentDataSetReader->state;
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_StatusCode
+UA_DataSetReader_setState_disabled(UA_Server *server, UA_DataSetReader *dsr) {
+ UA_StatusCode ret = UA_STATUSCODE_GOOD;
+ switch(dsr->state) {
+ case UA_PUBSUBSTATE_DISABLED:
+ return UA_STATUSCODE_GOOD;
+ case UA_PUBSUBSTATE_PAUSED:
+ dsr->state = UA_PUBSUBSTATE_DISABLED;
+ return UA_STATUSCODE_GOOD;
+ case UA_PUBSUBSTATE_OPERATIONAL:
+#ifdef UA_ENABLE_PUBSUB_MONITORING
+ /* Stop MessageReceiveTimeout timer */
+ if(dsr->msgRcvTimeoutTimerRunning == UA_TRUE) {
+ ret = server->config.pubSubConfig.monitoringInterface.
+ stopMonitoring(server, dsr->identifier,
+ UA_PUBSUB_COMPONENT_DATASETREADER,
+ UA_PUBSUB_MONITORING_MESSAGE_RECEIVE_TIMEOUT, dsr);
+ if(ret == UA_STATUSCODE_GOOD) {
+ dsr->msgRcvTimeoutTimerRunning = UA_FALSE;
+ } else {
+ UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Disable ReaderGroup failed. Stop message receive "
+ "timeout timer of DataSetReader '%.*s' failed.",
+ (int) dsr->config.name.length, dsr->config.name.data);
+ }
+ }
+#endif /* UA_ENABLE_PUBSUB_MONITORING */
+ if(ret == UA_STATUSCODE_GOOD)
+ dsr->state = UA_PUBSUBSTATE_DISABLED;
+ return ret;
+ case UA_PUBSUBSTATE_ERROR:
+ break;
+ default:
+ UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Received unknown PubSub state!");
}
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+}
+/* State machine methods not part of the open62541 state machine API */
+UA_StatusCode
+UA_DataSetReader_setPubSubState(UA_Server *server, UA_PubSubState state,
+ UA_DataSetReader *dataSetReader) {
+ switch(state) {
+ case UA_PUBSUBSTATE_DISABLED:
+ return UA_DataSetReader_setState_disabled(server, dataSetReader);
+ case UA_PUBSUBSTATE_PAUSED:
+ return UA_STATUSCODE_BADNOTSUPPORTED;
+ case UA_PUBSUBSTATE_OPERATIONAL:
+ dataSetReader->state = UA_PUBSUBSTATE_OPERATIONAL;
+ break;
+ case UA_PUBSUBSTATE_ERROR:
+ dataSetReader->state = UA_PUBSUBSTATE_ERROR;
+ break;
+ default:
+ UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Received unknown PubSub state!");
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+ }
return UA_STATUSCODE_GOOD;
}
+UA_StatusCode
+UA_FieldTargetVariable_copy(const UA_FieldTargetVariable *src, UA_FieldTargetVariable *dst) {
+ /* Do a simple memcpy */
+ memcpy(dst, src, sizeof(UA_FieldTargetVariable));
+ return UA_FieldTargetDataType_copy(&src->targetVariable, &dst->targetVariable);
+}
+
+UA_StatusCode
+UA_TargetVariables_copy(const UA_TargetVariables *src, UA_TargetVariables *dst) {
+ UA_StatusCode retVal = UA_STATUSCODE_GOOD;
+ memcpy(dst, src, sizeof(UA_TargetVariables));
+ if(src->targetVariablesSize > 0) {
+ dst->targetVariables = (UA_FieldTargetVariable*)
+ UA_calloc(src->targetVariablesSize, sizeof(UA_FieldTargetVariable));
+ if(!dst->targetVariables)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ for(size_t i = 0; i < src->targetVariablesSize; i++)
+ retVal |= UA_FieldTargetVariable_copy(&src->targetVariables[i], &dst->targetVariables[i]);
+ }
+ return retVal;
+}
+
+void
+UA_TargetVariables_clear(UA_TargetVariables *subscribedDataSetTarget) {
+ for(size_t i = 0; i < subscribedDataSetTarget->targetVariablesSize; i++) {
+ UA_FieldTargetDataType_clear(&subscribedDataSetTarget->targetVariables[i].targetVariable);
+ }
+ if(subscribedDataSetTarget->targetVariablesSize > 0)
+ UA_free(subscribedDataSetTarget->targetVariables);
+ memset(subscribedDataSetTarget, 0, sizeof(UA_TargetVariables));
+}
+
/* This Method is used to initially set the SubscribedDataSet to
* TargetVariablesType and to create the list of target Variables of a
* SubscribedDataSetType. */
UA_StatusCode
UA_Server_DataSetReader_createTargetVariables(UA_Server *server,
UA_NodeId dataSetReaderIdentifier,
- UA_TargetVariablesDataType *targetVariables) {
- UA_StatusCode retval = UA_STATUSCODE_BADUNEXPECTEDERROR;
- UA_DataSetReader* pDS = UA_ReaderGroup_findDSRbyId(server, dataSetReaderIdentifier);
- if(pDS == NULL) {
+ size_t targetVariablesSize,
+ const UA_FieldTargetVariable *targetVariables) {
+ UA_DataSetReader *dataSetReader = UA_ReaderGroup_findDSRbyId(server, dataSetReaderIdentifier);
+ if(!dataSetReader)
return UA_STATUSCODE_BADINVALIDARGUMENT;
- }
- if(pDS->subscribedDataSetTarget.targetVariablesSize > 0) {
- UA_TargetVariablesDataType_deleteMembers(&pDS->subscribedDataSetTarget);
- pDS->subscribedDataSetTarget.targetVariablesSize = 0;
- pDS->subscribedDataSetTarget.targetVariables = NULL;
+ if(dataSetReader->configurationFrozen) {
+ UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Create Target Variables failed. Subscriber configuration is frozen.");
+ return UA_STATUSCODE_BADCONFIGURATIONERROR;
}
+ if(dataSetReader->config.subscribedDataSet.subscribedDataSetTarget.targetVariablesSize > 0)
+ UA_TargetVariables_clear(&dataSetReader->config.subscribedDataSet.subscribedDataSetTarget);
+
/* Set subscribed dataset to TargetVariableType */
- pDS->subscribedDataSetType = UA_PUBSUB_SDS_TARGET;
- retval = UA_TargetVariablesDataType_copy(targetVariables, &pDS->subscribedDataSetTarget);
- return retval;
+ dataSetReader->config.subscribedDataSetType = UA_PUBSUB_SDS_TARGET;
+ UA_TargetVariables tmp;
+ tmp.targetVariablesSize = targetVariablesSize;
+ tmp.targetVariables = (UA_FieldTargetVariable*)(uintptr_t)targetVariables;
+ return UA_TargetVariables_copy(&tmp, &dataSetReader->config.subscribedDataSet.subscribedDataSetTarget);
}
-/* Adds Subscribed Variables from the DataSetMetaData for the given DataSet into
- * the given parent node and creates the corresponding data in the
- * targetVariables of the DataSetReader */
-UA_StatusCode
-UA_Server_DataSetReader_addTargetVariables(UA_Server *server, UA_NodeId *parentNode,
- UA_NodeId dataSetReaderIdentifier,
- UA_SubscribedDataSetEnumType sdsType) {
+/* This functionality of this API will be used in future to create mirror Variables - TODO */
+/* UA_StatusCode
+UA_Server_DataSetReader_createDataSetMirror(UA_Server *server, UA_String *parentObjectNodeName,
+ UA_NodeId dataSetReaderIdentifier) {
if((server == NULL) || (parentNode == NULL)) {
return UA_STATUSCODE_BADINVALIDARGUMENT;
}
@@ -30681,12 +31158,18 @@ UA_Server_DataSetReader_addTargetVariables(UA_Server *server, UA_NodeId *parentN
return UA_STATUSCODE_BADINVALIDARGUMENT;
}
- UA_TargetVariablesDataType targetVars;
+ if(pDataSetReader->configurationFrozen) {
+ UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Add Target Variables failed. Subscriber configuration is frozen.");
+ return UA_STATUSCODE_BADCONFIGURATIONERROR;
+ } // TODO: Frozen configuration variable in TargetVariable structure
+
+ UA_TargetVariables targetVars;
targetVars.targetVariablesSize = pDataSetReader->config.dataSetMetaData.fieldsSize;
- targetVars.targetVariables = (UA_FieldTargetDataType*)
- UA_calloc(targetVars.targetVariablesSize, sizeof(UA_FieldTargetDataType));
+ targetVars.targetVariables = (UA_FieldTargetVariable *)
+ UA_calloc(targetVars.targetVariablesSize, sizeof(UA_FieldTargetVariable));
- for (size_t i = 0; i < pDataSetReader->config.dataSetMetaData.fieldsSize; i++) {
+ for(size_t i = 0; i < pDataSetReader->config.dataSetMetaData.fieldsSize; i++) {
UA_VariableAttributes vAttr = UA_VariableAttributes_default;
vAttr.valueRank = pDataSetReader->config.dataSetMetaData.fields[i].valueRank;
if(pDataSetReader->config.dataSetMetaData.fields[i].arrayDimensionsSize > 0) {
@@ -30727,7 +31210,7 @@ UA_Server_DataSetReader_addTargetVariables(UA_Server *server, UA_NodeId *parentN
qn = UA_QUALIFIEDNAME(1, "SubscribedVariable");
}
- /* Add variable to the given parent node */
+ // Add variable to the given parent node
UA_NodeId newNode;
retval = UA_Server_addVariableNode(server, UA_NODEID_NULL, *parentNode,
UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), qn,
@@ -30742,151 +31225,1309 @@ UA_Server_DataSetReader_addTargetVariables(UA_Server *server, UA_NodeId *parentN
"addVariableNode: error 0x%" PRIx32, retval);
}
- UA_FieldTargetDataType_init(&targetVars.targetVariables[i]);
- targetVars.targetVariables[i].attributeId = UA_ATTRIBUTEID_VALUE;
- UA_NodeId_copy(&newNode, &targetVars.targetVariables[i].targetNodeId);
- UA_NodeId_deleteMembers(&newNode);
+ targetVars.targetVariables[i].targetVariable.attributeId = UA_ATTRIBUTEID_VALUE;
+ UA_NodeId_copy(&newNode, &targetVars.targetVariables[i].targetVariable.targetNodeId);
+ UA_NodeId_clear(&newNode);
if(vAttr.arrayDimensionsSize > 0) {
UA_Array_delete(vAttr.arrayDimensions, vAttr.arrayDimensionsSize,
&UA_TYPES[UA_TYPES_UINT32]);
}
}
- if(sdsType == UA_PUBSUB_SDS_TARGET) {
- retval = UA_Server_DataSetReader_createTargetVariables(server, pDataSetReader->identifier,
- &targetVars);
+ UA_TargetVariables_clear(&targetVars);
+ return retval;
+}*/
+
+static void
+DataSetReader_processRaw(UA_Server *server, UA_ReaderGroup *rg,
+ UA_DataSetReader *dsr, UA_DataSetMessage* msg) {
+ UA_LOG_TRACE(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Received RAW Frame");
+ msg->data.keyFrameData.fieldCount = (UA_UInt16)
+ dsr->config.dataSetMetaData.fieldsSize;
+
+ size_t offset = 0;
+ for(size_t i = 0; i < dsr->config.dataSetMetaData.fieldsSize; i++) {
+ /* TODO The datatype reference should be part of the internal
+ * pubsub configuration to avoid the time-expensive lookup */
+ const UA_DataType *type =
+ UA_findDataTypeWithCustom(&dsr->config.dataSetMetaData.fields[i].dataType,
+ server->config.customDataTypes);
+ msg->data.keyFrameData.rawFields.length += type->memSize;
+ UA_STACKARRAY(UA_Byte, value, type->memSize);
+ UA_StatusCode res =
+ UA_decodeBinaryInternal(&msg->data.keyFrameData.rawFields,
+ &offset, value, type, NULL);
+ if(res != UA_STATUSCODE_GOOD) {
+ UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Error during Raw-decode KeyFrame field %u: %s",
+ (unsigned)i, UA_StatusCode_name(res));
+ return;
+ }
+
+ UA_FieldTargetVariable *tv =
+ &dsr->config.subscribedDataSet.subscribedDataSetTarget.targetVariables[i];
+
+ if(rg->config.rtLevel == UA_PUBSUB_RT_FIXED_SIZE) {
+ if (tv->beforeWrite) {
+ void *pData = (**tv->externalDataValue).value.data;
+ (**tv->externalDataValue).value.data = value; // set raw data as "preview"
+ tv->beforeWrite(server,
+ &dsr->identifier,
+ &dsr->linkedReaderGroup,
+ &dsr->config.subscribedDataSet.subscribedDataSetTarget.targetVariables[i].targetVariable.targetNodeId,
+ dsr->config.subscribedDataSet.subscribedDataSetTarget.targetVariables[i].targetVariableContext,
+ tv->externalDataValue);
+ (**tv->externalDataValue).value.data = pData; // restore previous data pointer
+ }
+ memcpy((**tv->externalDataValue).value.data, value, type->memSize);
+ if(tv->afterWrite)
+ tv->afterWrite(server, &dsr->identifier,
+ &dsr->linkedReaderGroup,
+ &tv->targetVariable.targetNodeId,
+ tv->targetVariableContext,
+ tv->externalDataValue);
+ continue; /* No dynamic allocation for fixed-size msg, no need to _clear */
+ }
+
+ UA_WriteValue writeVal;
+ UA_WriteValue_init(&writeVal);
+ writeVal.attributeId = tv->targetVariable.attributeId;
+ writeVal.indexRange = tv->targetVariable.receiverIndexRange;
+ writeVal.nodeId = tv->targetVariable.targetNodeId;
+ UA_Variant_setScalar(&writeVal.value.value, value, type);
+ writeVal.value.hasValue = true;
+ res = UA_Server_write(server, &writeVal);
+ UA_clear(value, type);
+ if(res != UA_STATUSCODE_GOOD) {
+ UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Error writing KeyFrame field %u: %s",
+ (unsigned)i, UA_StatusCode_name(res));
+ }
}
+}
- UA_TargetVariablesDataType_deleteMembers(&targetVars);
- return retval;
+static void
+DataSetReader_processFixedSize(UA_Server *server, UA_ReaderGroup *rg,
+ UA_DataSetReader *dsr, UA_DataSetMessage *msg,
+ size_t fieldCount) {
+ for(size_t i = 0; i < fieldCount; i++) {
+ if(!msg->data.keyFrameData.dataSetFields[i].hasValue)
+ continue;
+
+ UA_FieldTargetVariable *tv =
+ &dsr->config.subscribedDataSet.subscribedDataSetTarget.targetVariables[i];
+ if(tv->targetVariable.attributeId != UA_ATTRIBUTEID_VALUE)
+ continue;
+ if (tv->beforeWrite) {
+ UA_DataValue *tmp = &msg->data.keyFrameData.dataSetFields[i];
+ tv->beforeWrite(server,
+ &dsr->identifier,
+ &dsr->linkedReaderGroup,
+ &dsr->config.subscribedDataSet.subscribedDataSetTarget.targetVariables[i].targetVariable.targetNodeId,
+ dsr->config.subscribedDataSet.subscribedDataSetTarget.targetVariables[i].targetVariableContext,
+ &tmp);
+ }
+ memcpy((**tv->externalDataValue).value.data,
+ msg->data.keyFrameData.dataSetFields[i].value.data,
+ msg->data.keyFrameData.dataSetFields[i].value.type->memSize);
+ if(tv->afterWrite)
+ tv->afterWrite(server, &dsr->identifier, &dsr->linkedReaderGroup,
+ &tv->targetVariable.targetNodeId,
+ tv->targetVariableContext, tv->externalDataValue);
+ }
}
void
-UA_Server_DataSetReader_process(UA_Server *server, UA_DataSetReader *dataSetReader,
- UA_DataSetMessage* dataSetMsg) {
- if((dataSetReader == NULL) || (dataSetMsg == NULL) || (server == NULL)) {
+UA_DataSetReader_process(UA_Server *server, UA_ReaderGroup *rg,
+ UA_DataSetReader *dsr, UA_DataSetMessage *msg) {
+ if(!dsr || !rg || !msg || !server)
return;
- }
- if(!dataSetMsg->header.dataSetMessageValid) {
+ UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "DataSetReader '%.*s': received a network message",
+ (int) dsr->config.name.length, dsr->config.name.data);
+
+ if(!msg->header.dataSetMessageValid) {
UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_SERVER,
"DataSetMessage is discarded: message is not valid");
- /* To Do check ConfigurationVersion*/
- /*if(dataSetMsg->header.configVersionMajorVersionEnabled)
- * {
- * if(dataSetMsg->header.configVersionMajorVersion != dataSetReader->config.dataSetMetaData.configurationVersion.majorVersion)
- * {
- * UA_LOG_WARNING(server->config.logger, UA_LOGCATEGORY_SERVER, "DataSetMessage is discarded: ConfigurationVersion MajorVersion does not match");
- * return;
- * }
- } */
+ /* To Do check ConfigurationVersion */
+ /* if(msg->header.configVersionMajorVersionEnabled) {
+ * if(msg->header.configVersionMajorVersion !=
+ * dsr->config.dataSetMetaData.configurationVersion.majorVersion) {
+ * UA_LOG_WARNING(server->config.logger, UA_LOGCATEGORY_SERVER,
+ * "DataSetMessage is discarded: ConfigurationVersion "
+ * "MajorVersion does not match");
+ * return;
+ * }
+ * } */
return;
}
- if(dataSetMsg->header.dataSetMessageType == UA_DATASETMESSAGE_DATAKEYFRAME) {
- if(dataSetMsg->header.fieldEncoding != UA_FIELDENCODING_RAWDATA) {
- size_t anzFields = dataSetMsg->data.keyFrameData.fieldCount;
- if(dataSetReader->config.dataSetMetaData.fieldsSize < anzFields) {
- anzFields = dataSetReader->config.dataSetMetaData.fieldsSize;
- }
+ if(msg->header.dataSetMessageType != UA_DATASETMESSAGE_DATAKEYFRAME) {
+ UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "DataSetMessage is discarded: Only keyframes are supported");
+ return;
+ }
- if(dataSetReader->subscribedDataSetTarget.targetVariablesSize < anzFields) {
- anzFields = dataSetReader->subscribedDataSetTarget.targetVariablesSize;
- }
+ /* Process message with raw encoding (realtime and non-realtime) */
+ if(msg->header.fieldEncoding == UA_FIELDENCODING_RAWDATA) {
+ DataSetReader_processRaw(server, rg, dsr, msg);
+#ifdef UA_ENABLE_PUBSUB_MONITORING
+ UA_DataSetReader_checkMessageReceiveTimeout(server, dsr);
+#endif
+ return;
+ }
- UA_StatusCode retVal = UA_STATUSCODE_GOOD;
- for(UA_UInt16 i = 0; i < anzFields; i++) {
- if(dataSetMsg->data.keyFrameData.dataSetFields[i].hasValue) {
- if(dataSetReader->subscribedDataSetTarget.targetVariables[i].attributeId == UA_ATTRIBUTEID_VALUE) {
- retVal = UA_Server_writeValue(server, dataSetReader->subscribedDataSetTarget.targetVariables[i].targetNodeId, dataSetMsg->data.keyFrameData.dataSetFields[i].value);
- if(retVal != UA_STATUSCODE_GOOD) {
- UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_SERVER, "Error Write Value KF %" PRIu16 ": 0x%"PRIx32, i, retVal);
- }
+ /* Check and adjust the field count
+ * TODO Throw an error if non-matching? */
+ size_t fieldCount = msg->data.keyFrameData.fieldCount;
+ if(dsr->config.dataSetMetaData.fieldsSize < fieldCount)
+ fieldCount = dsr->config.dataSetMetaData.fieldsSize;
- }
- else {
- UA_WriteValue writeVal;
- UA_WriteValue_init(&writeVal);
- writeVal.attributeId = dataSetReader->subscribedDataSetTarget.targetVariables[i].attributeId;
- writeVal.indexRange = dataSetReader->subscribedDataSetTarget.targetVariables[i].receiverIndexRange;
- writeVal.nodeId = dataSetReader->subscribedDataSetTarget.targetVariables[i].targetNodeId;
- UA_DataValue_copy(&dataSetMsg->data.keyFrameData.dataSetFields[i], &writeVal.value);
- retVal = UA_Server_write(server, &writeVal);
- if(retVal != UA_STATUSCODE_GOOD) {
- UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_SERVER, "Error Write KF %" PRIu16 ": 0x%" PRIx32, i, retVal);
- }
+ if(dsr->config.subscribedDataSet.subscribedDataSetTarget.targetVariablesSize < fieldCount)
+ fieldCount = dsr->config.subscribedDataSet.subscribedDataSetTarget.targetVariablesSize;
- }
+ /* Process message with fixed size fields (realtime capable) */
+ if(rg->config.rtLevel == UA_PUBSUB_RT_FIXED_SIZE) {
+ DataSetReader_processFixedSize(server, rg, dsr, msg, fieldCount);
+#ifdef UA_ENABLE_PUBSUB_MONITORING
+ UA_DataSetReader_checkMessageReceiveTimeout(server, dsr);
+#endif
+ return;
+ }
- }
+ /* Write the message fields via the write service (non realtime) */
+ UA_StatusCode res = UA_STATUSCODE_GOOD;
+ for(size_t i = 0; i < fieldCount; i++) {
+ if(!msg->data.keyFrameData.dataSetFields[i].hasValue)
+ continue;
- }
+ UA_FieldTargetVariable *tv =
+ &dsr->config.subscribedDataSet.subscribedDataSetTarget.targetVariables[i];
+ UA_WriteValue writeVal;
+ UA_WriteValue_init(&writeVal);
+ writeVal.attributeId = tv->targetVariable.attributeId;
+ writeVal.indexRange = tv->targetVariable.receiverIndexRange;
+ writeVal.nodeId = tv->targetVariable.targetNodeId;
+ writeVal.value = msg->data.keyFrameData.dataSetFields[i];
+ res = UA_Server_write(server, &writeVal);
+ if(res != UA_STATUSCODE_GOOD)
+ UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Error writing KeyFrame field %u: %s",
+ (unsigned)i, UA_StatusCode_name(res));
+ }
+
+#ifdef UA_ENABLE_PUBSUB_MONITORING
+ UA_DataSetReader_checkMessageReceiveTimeout(server, dsr);
+#endif
+}
+
+#ifdef UA_ENABLE_PUBSUB_MONITORING
+
+void
+UA_DataSetReader_checkMessageReceiveTimeout(UA_Server *server,
+ UA_DataSetReader *dsr) {
+ UA_assert(server != 0);
+ UA_assert(dsr != 0);
+
+ /* If previous reader state was error (because we haven't received messages
+ * and ran into timeout) we should set the state back to operational */
+ if(dsr->state == UA_PUBSUBSTATE_ERROR) {
+ UA_DataSetReader_setPubSubState(server, UA_PUBSUBSTATE_OPERATIONAL, dsr);
+ if(server->config.pubSubConfig.stateChangeCallback != 0) {
+ server->config.pubSubConfig.stateChangeCallback(&dsr->identifier,
+ UA_PUBSUBSTATE_OPERATIONAL,
+ UA_STATUSCODE_GOOD);
+ }
+ }
+
+ /* Stop message receive timeout timer */
+ UA_StatusCode res;
+ if(dsr->msgRcvTimeoutTimerRunning) {
+ res = server->config.pubSubConfig.monitoringInterface.
+ stopMonitoring(server, dsr->identifier, UA_PUBSUB_COMPONENT_DATASETREADER,
+ UA_PUBSUB_MONITORING_MESSAGE_RECEIVE_TIMEOUT, dsr);
+ if(res == UA_STATUSCODE_GOOD) {
+ dsr->msgRcvTimeoutTimerRunning = false;
+ } else {
+ UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "DataSetReader '%.*s': stop receive timeout timer failed",
+ (int)dsr->config.name.length, dsr->config.name.data);
+ UA_DataSetReader_setPubSubState(server, UA_PUBSUBSTATE_ERROR, dsr);
}
+ }
+
+ /* Start message receive timeout timer */
+ res = server->config.pubSubConfig.monitoringInterface.
+ startMonitoring(server, dsr->identifier, UA_PUBSUB_COMPONENT_DATASETREADER,
+ UA_PUBSUB_MONITORING_MESSAGE_RECEIVE_TIMEOUT, dsr);
+ if(res == UA_STATUSCODE_GOOD) {
+ UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Info: DataSetReader '%.*s': start receive timeout timer",
+ (int)dsr->config.name.length, dsr->config.name.data);
+ dsr->msgRcvTimeoutTimerRunning = true;
+ } else {
+ UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Starting Message Receive Timeout timer failed.");
+ UA_DataSetReader_setPubSubState(server, UA_PUBSUBSTATE_ERROR, dsr);
+ }
+}
+
+/* Timeout callback for DataSetReader MessageReceiveTimeout handling */
+void
+UA_DataSetReader_handleMessageReceiveTimeout(UA_Server *server,
+ void *dataSetReader) {
+ if(!server || !dataSetReader) {
+ UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "UA_DataSetReader_handleMessageReceiveTimeout(): "
+ "null pointer param");
+ return;
+ }
+
+ UA_DataSetReader *dsr = (UA_DataSetReader*) dataSetReader;
+ if(dsr->componentType != UA_PUBSUB_COMPONENT_DATASETREADER) {
+ UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "UA_DataSetReader_handleMessageReceiveTimeout(): "
+ "input param is not of type DataSetReader");
+ return;
+ }
+ UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "UA_DataSetReader_handleMessageReceiveTimeout(): "
+ "MessageReceiveTimeout occurred at DataSetReader "
+ "'%.*s': MessageReceiveTimeout = %f Timer Id = %u ",
+ (int)dsr->config.name.length, dsr->config.name.data,
+ dsr->config.messageReceiveTimeout,
+ (UA_UInt32) dsr->msgRcvTimeoutTimerId);
+
+ UA_ServerConfig *pConfig = UA_Server_getConfig(server);
+ if(pConfig->pubSubConfig.stateChangeCallback != 0) {
+ pConfig->pubSubConfig.stateChangeCallback(&dsr->identifier,
+ UA_PUBSUBSTATE_ERROR,
+ UA_STATUSCODE_BADTIMEOUT);
+ }
+
+ UA_StatusCode res =
+ UA_DataSetReader_setPubSubState(server, UA_PUBSUBSTATE_ERROR, dsr);
+ if(res != UA_STATUSCODE_GOOD) {
+ UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "UA_DataSetReader_handleMessageReceiveTimeout(): "
+ "setting pubsub state failed");
}
}
+#endif /* UA_ENABLE_PUBSUB_MONITORING */
-void UA_DataSetReader_delete(UA_Server *server, UA_DataSetReader *dataSetReader) {
+static void
+UA_DataSetReader_clear(UA_Server *server, UA_DataSetReader *dsr) {
/* Delete DataSetReader config */
- UA_String_deleteMembers(&dataSetReader->config.name);
- UA_Variant_deleteMembers(&dataSetReader->config.publisherId);
- UA_DataSetMetaDataType_deleteMembers(&dataSetReader->config.dataSetMetaData);
- UA_UadpDataSetReaderMessageDataType_deleteMembers(&dataSetReader->config.messageSettings);
- UA_ExtensionObject_clear(&dataSetReader->config.transportSettings);
- UA_TargetVariablesDataType_deleteMembers(&dataSetReader->subscribedDataSetTarget);
+ UA_DataSetReaderConfig_clear(&dsr->config);
/* Delete DataSetReader */
- UA_ReaderGroup* pGroup = UA_ReaderGroup_findRGbyId(server, dataSetReader->linkedReaderGroup);
- if(pGroup != NULL) {
- pGroup->readersCount--;
+ UA_ReaderGroup *rg = UA_ReaderGroup_findRGbyId(server, dsr->linkedReaderGroup);
+ if(rg)
+ rg->readersCount--;
+
+ UA_NodeId_clear(&dsr->identifier);
+ UA_NodeId_clear(&dsr->linkedReaderGroup);
+ if(dsr->config.subscribedDataSetType == UA_PUBSUB_SDS_TARGET) {
+ UA_TargetVariables_clear(&dsr->config.subscribedDataSet.subscribedDataSetTarget);
+ } else {
+ UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "UA_DataSetReader_clear(): unsupported subscribed dataset enum type");
}
- UA_NodeId_deleteMembers(&dataSetReader->identifier);
- UA_NodeId_deleteMembers(&dataSetReader->linkedReaderGroup);
/* Remove DataSetReader from group */
- LIST_REMOVE(dataSetReader, listEntry);
+ LIST_REMOVE(dsr, listEntry);
+
/* Free memory allocated for DataSetReader */
- UA_free(dataSetReader);
+ UA_free(dsr);
+}
+
+static void
+processMessageWithReader(UA_Server *server, UA_ReaderGroup *readerGroup,
+ UA_DataSetReader *reader, UA_NetworkMessage *msg) {
+ UA_Byte totalDataSets = 1;
+ if(msg->payloadHeaderEnabled)
+ totalDataSets = msg->payloadHeader.dataSetPayloadHeader.count;
+ for(UA_Byte i = 0; i < totalDataSets; i++) {
+ UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Process Msg with DataSetReader!");
+ UA_DataSetReader_process(server, readerGroup, reader,
+ &msg->payload.dataSetPayload.dataSetMessages[i]);
+ }
}
UA_StatusCode
-UA_Server_processNetworkMessage(UA_Server *server, UA_NetworkMessage *pMsg,
- UA_PubSubConnection *pConnection) {
- UA_StatusCode retval = UA_STATUSCODE_GOOD;
- if(!pMsg || !pConnection)
+UA_Server_processNetworkMessage(UA_Server *server, UA_PubSubConnection *connection,
+ UA_NetworkMessage* msg) {
+ if(!msg || !connection)
return UA_STATUSCODE_BADINVALIDARGUMENT;
- /* To Do Handle multiple DataSetMessage for one NetworkMessage */
/* To Do The condition pMsg->dataSetClassIdEnabled
* Here some filtering is possible */
+ if(!msg->publisherIdEnabled) {
+ UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Cannot process DataSetReader without PublisherId");
+ return UA_STATUSCODE_BADNOTIMPLEMENTED; /* TODO: Handle DSR without PublisherId */
+ }
+
+ /* There can be several readers listening for the same network message */
+ UA_Boolean processed = false;
+ UA_ReaderGroup *readerGroup;
+ UA_DataSetReader *reader;
+ LIST_FOREACH(readerGroup, &connection->readerGroups, listEntry) {
+ LIST_FOREACH(reader, &readerGroup->readers, listEntry) {
+ UA_StatusCode retval = checkReaderIdentifier(server, msg, reader);
+ if(retval == UA_STATUSCODE_GOOD) {
+ processed = true;
+ processMessageWithReader(server, readerGroup, reader, msg);
+ }
+ }
+ }
+
+ if(!processed) {
+ UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Dataset reader not found. Check PublisherID, WriterGroupID "
+ "and DatasetWriterID");
+ }
+
+ return UA_STATUSCODE_GOOD;
+}
+
+/********************************************************************************
+ * Functionality related to decoding, decrypting and processing network messages
+ * as a subscriber
+ ********************************************************************************/
+
+#define MIN_PAYLOAD_SIZE_ETHERNET 46
+
+/* Delete the payload value of every decoded DataSet field */
+static void UA_DataSetMessage_freeDecodedPayload(UA_DataSetMessage *dsm) {
+ if(dsm->header.fieldEncoding == UA_FIELDENCODING_VARIANT) {
+ for(size_t i = 0; i < dsm->data.keyFrameData.fieldCount; i++) {
+#ifdef UA_ENABLE_PUBSUB_BUFMALLOC
+ UA_Variant_init(&dsm->data.keyFrameData.dataSetFields[i].value);
+#else
+ UA_Variant_clear(&dsm->data.keyFrameData.dataSetFields[i].value);
+#endif
+ }
+ }
+ else if(dsm->header.fieldEncoding == UA_FIELDENCODING_DATAVALUE) {
+ for(size_t i = 0; i < dsm->data.keyFrameData.fieldCount; i++) {
+#ifdef UA_ENABLE_PUBSUB_BUFMALLOC
+ UA_DataValue_init(&dsm->data.keyFrameData.dataSetFields[i]);
+#else
+ UA_DataValue_clear(&dsm->data.keyFrameData.dataSetFields[i]);
+#endif
+ }
+ }
+}
+
+UA_StatusCode
+decodeNetworkMessage(UA_Server *server, UA_ByteString *buffer, size_t *pos,
+ UA_NetworkMessage *nm, UA_PubSubConnection *connection) {
+#ifdef UA_DEBUG_DUMP_PKGS
+ UA_dump_hex_pkg(buffer->data, buffer->length);
+#endif
+
+ UA_StatusCode rv = UA_NetworkMessage_decodeHeaders(buffer, pos, nm);
+ UA_CHECK_STATUS_ERROR(rv, return rv,
+ &server->config.logger, UA_LOGCATEGORY_SERVER,
+ "PubSub receive. decoding headers failed");
+
+#ifdef UA_ENABLE_PUBSUB_ENCRYPTION
+ UA_Boolean processed = false;
+ UA_ReaderGroup *readerGroup;
+ UA_DataSetReader *reader;
+
+ /* Choose a correct readergroup for decrypt/verify this message
+ * (there could be multiple) */
+ LIST_FOREACH(readerGroup, &connection->readerGroups, listEntry) {
+ LIST_FOREACH(reader, &readerGroup->readers, listEntry) {
+ UA_StatusCode retval = checkReaderIdentifier(server, nm, reader);
+ if(retval == UA_STATUSCODE_GOOD) {
+ processed = true;
+ rv = verifyAndDecryptNetworkMessage(&server->config.logger, buffer, pos,
+ nm, readerGroup);
+ UA_CHECK_STATUS_WARN(rv, return rv,
+ &server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Subscribe failed. verify and decrypt network message failed.");
+
+#ifdef UA_DEBUG_DUMP_PKGS
+ UA_dump_hex_pkg(buffer->data, buffer->length);
+#endif
+ /* break out of all loops when first verify & decrypt was successful */
+ goto loops_exit;
+ }
+ }
+ }
+
+loops_exit:
+ if(!processed) {
+ UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Dataset reader not found. Check PublisherId, "
+ "WriterGroupId and DatasetWriterId");
+ /* Possible multicast scenario: there are multiple connections (with one
+ * or more ReaderGroups) within a multicast group every connection
+ * receives all network messages, even if some of them are not meant for
+ * the connection currently processed -> therefore it is ok if the
+ * connection does not have a DataSetReader for every received network
+ * message. We must not return an error here, but continue with the
+ * buffer decoding and see if we have a matching DataSetReader for the
+ * next network message. */
+ }
+#endif
+
+ rv = UA_NetworkMessage_decodePayload(buffer, pos, nm);
+ UA_CHECK_STATUS(rv, return rv);
+
+ rv = UA_NetworkMessage_decodeFooters(buffer, pos, nm);
+ UA_CHECK_STATUS(rv, return rv);
+
+ return UA_STATUSCODE_GOOD;
+}
+
+static
+UA_StatusCode
+decodeAndProcessNetworkMessage(UA_Server *server, UA_ReaderGroup *readerGroup,
+ UA_PubSubConnection *connection,
+ UA_ByteString *buffer) {
+ UA_NetworkMessage nm;
+ memset(&nm, 0, sizeof(UA_NetworkMessage));
+ size_t currentPosition = 0;
+
+ UA_StatusCode rv = UA_STATUSCODE_GOOD;
+ rv = decodeNetworkMessage(server, buffer, &currentPosition, &nm, connection);
+ UA_CHECK_STATUS_WARN(rv, goto cleanup, &server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Subscribe failed. verify, decrypt and decode network message failed.");
+
+ rv = UA_Server_processNetworkMessage(server, connection, &nm);
+ // TODO: check what action to perform on error (nothing?)
+ UA_CHECK_STATUS_WARN(rv, (void)0, &server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Subscribe failed. process network message failed.");
+
+cleanup:
+ UA_NetworkMessage_clear(&nm);
+ return rv;
+}
+
+static
+UA_StatusCode
+decodeAndProcessNetworkMessageRT(UA_Server *server, UA_ReaderGroup *readerGroup,
+ UA_PubSubConnection *connection,
+ UA_ByteString *buffer) {
+#ifdef UA_ENABLE_PUBSUB_BUFMALLOC
+ useMembufAlloc();
+#endif
+
+ /* Considering max DSM as 1
+ * TODO: Process with the static value source */
+ size_t currentPosition = 0;
+ UA_DataSetReader *dataSetReader = LIST_FIRST(&readerGroup->readers);
+ UA_NetworkMessage *nm = dataSetReader->bufferedMessage.nm;
+
+ /* Decode only the necessary offset and update the networkMessage */
+ UA_StatusCode res =
+ UA_NetworkMessage_updateBufferedNwMessage(&dataSetReader->bufferedMessage,
+ buffer, &currentPosition);
+ if(res != UA_STATUSCODE_GOOD) {
+ UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "PubSub receive. Unknown field type.");
+ res = UA_STATUSCODE_UNCERTAIN;
+ goto cleanup;
+ }
+
+ /* Check the decoded message is the expected one
+ * TODO: PublisherID check after modification in NM to support all datatypes */
+ if(nm->groupHeader.writerGroupId != dataSetReader->config.writerGroupId ||
+ *nm->payloadHeader.dataSetPayloadHeader.dataSetWriterIds != dataSetReader->config.dataSetWriterId) {
+ UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "PubSub receive. Unknown message received. Will not be processed.");
+ res = UA_STATUSCODE_UNCERTAIN;
+ goto cleanup;
+ }
+
+ UA_DataSetReader_process(server, readerGroup, dataSetReader,
+ nm->payload.dataSetPayload.dataSetMessages);
+
+ cleanup:
+ UA_DataSetMessage_freeDecodedPayload(nm->payload.dataSetPayload.dataSetMessages);
+#ifdef UA_ENABLE_PUBSUB_BUFMALLOC
+ useNormalAlloc();
+#endif
+ return res;
+}
+
+typedef struct {
+ UA_Server *server;
+ UA_PubSubConnection *connection;
+ UA_ReaderGroup *readerGroup;
+} UA_RGContext;
+
+static UA_StatusCode
+decodeAndProcessFun(UA_PubSubChannel *channel, void *cbContext,
+ const UA_ByteString *buffer) {
+ UA_ByteString mutableBuffer = {buffer->length, buffer->data};
+ UA_RGContext *ctx = (UA_RGContext*) cbContext;
+ return decodeAndProcessNetworkMessage(ctx->server, ctx->readerGroup,
+ ctx->connection, &mutableBuffer);
+}
+
+static UA_StatusCode
+decodeAndProcessFunRT(UA_PubSubChannel *channel, void *cbContext,
+ const UA_ByteString *buffer) {
+ UA_ByteString mutableBuffer = {buffer->length, buffer->data};
+ UA_RGContext *ctx = (UA_RGContext*) cbContext;
+ return decodeAndProcessNetworkMessageRT(ctx->server, ctx->readerGroup,
+ ctx->connection, &mutableBuffer);
+}
+
+UA_StatusCode
+receiveBufferedNetworkMessage(UA_Server *server, UA_ReaderGroup *readerGroup,
+ UA_PubSubConnection *connection) {
+ UA_RGContext ctx = {server, connection, readerGroup};
+ UA_PubSubReceiveCallback receiveCB;
+ if(readerGroup->config.rtLevel == UA_PUBSUB_RT_FIXED_SIZE)
+ receiveCB = decodeAndProcessFunRT;
+ else
+ receiveCB = decodeAndProcessFun;
+
+ /* TODO: Move the TransportSettings to to the readerGroupConfig. So we can
+ * use it here instead of a NULL pointer. */
+ UA_StatusCode rv =
+ connection->channel->receive(connection->channel, NULL,
+ receiveCB, &ctx,
+ readerGroup->config.timeout);
+
+ // TODO attention: here rv is ok if UA_STATUSCODE_GOOD != rv
+ UA_CHECK_WARN(!UA_StatusCode_isBad(rv), return rv,
+ &server->config.logger, UA_LOGCATEGORY_SERVER,
+ "SubscribeCallback(): Connection receive failed!");
+
+ return UA_STATUSCODE_GOOD;
+}
+
+#endif /* UA_ENABLE_PUBSUB */
+
+/**** amalgamated original file "/src/pubsub/ua_pubsub_readergroup.c" ****/
+
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Copyright (c) 2017-2018 Fraunhofer IOSB (Author: Andreas Ebner)
+ * Copyright (c) 2019 Fraunhofer IOSB (Author: Julius Pfrommer)
+ * Copyright (c) 2019 Kalycito Infotech Private Limited
+ * Copyright (c) 2021 Fraunhofer IOSB (Author: Jan Hermes)
+ */
+
+
+
+#ifdef UA_ENABLE_PUBSUB /* conditional compilation */
+
+
+#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL
+#endif
+
+UA_ReaderGroup *
+UA_ReaderGroup_findRGbyId(UA_Server *server, UA_NodeId identifier) {
+ UA_PubSubConnection *pubSubConnection;
+ TAILQ_FOREACH(pubSubConnection, &server->pubSubManager.connections, listEntry){
+ UA_ReaderGroup* readerGroup = NULL;
+ LIST_FOREACH(readerGroup, &pubSubConnection->readerGroups, listEntry) {
+ if(UA_NodeId_equal(&identifier, &readerGroup->identifier))
+ return readerGroup;
+ }
+ }
+ return NULL;
+}
+
+UA_DataSetReader *UA_ReaderGroup_findDSRbyId(UA_Server *server, UA_NodeId identifier) {
+ UA_PubSubConnection *pubSubConnection;
+ TAILQ_FOREACH(pubSubConnection, &server->pubSubManager.connections, listEntry){
+ UA_ReaderGroup* readerGroup = NULL;
+ LIST_FOREACH(readerGroup, &pubSubConnection->readerGroups, listEntry) {
+ UA_DataSetReader *tmpReader;
+ LIST_FOREACH(tmpReader, &readerGroup->readers, listEntry) {
+ if(UA_NodeId_equal(&tmpReader->identifier, &identifier))
+ return tmpReader;
+ }
+ }
+ }
+ return NULL;
+}
+
+/* Clear ReaderGroup */
+static void
+UA_Server_ReaderGroup_clear(UA_Server* server, UA_ReaderGroup *readerGroup);
+
+/* ReaderGroup Config Handling */
+
+UA_StatusCode
+UA_ReaderGroupConfig_copy(const UA_ReaderGroupConfig *src,
+ UA_ReaderGroupConfig *dst) {
+ memcpy(dst, src, sizeof(UA_ReaderGroupConfig));
+
+ UA_StatusCode res = UA_String_copy(&src->name, &dst->name);
+ if(res != UA_STATUSCODE_GOOD)
+ return res;
+
+ res = UA_Array_copy(src->groupProperties, src->groupPropertiesSize,
+ (void**)&dst->groupProperties,
+ &UA_TYPES[UA_TYPES_KEYVALUEPAIR]);
+ if(res != UA_STATUSCODE_GOOD) {
+ UA_String_clear(&dst->name);
+ return res;
+ }
+ dst->groupPropertiesSize = src->groupPropertiesSize;
+ return UA_STATUSCODE_GOOD;
+}
+
+void
+UA_ReaderGroupConfig_clear(UA_ReaderGroupConfig *readerGroupConfig) {
+ UA_String_clear(&readerGroupConfig->name);
+ UA_Array_delete(readerGroupConfig->groupProperties,
+ readerGroupConfig->groupPropertiesSize,
+ &UA_TYPES[UA_TYPES_KEYVALUEPAIR]);
+ readerGroupConfig->groupProperties = NULL;
+ readerGroupConfig->groupPropertiesSize = 0;
+}
+
+/* ReaderGroup Lifecycle */
+
+UA_StatusCode
+UA_Server_addReaderGroup(UA_Server *server, UA_NodeId connectionIdentifier,
+ const UA_ReaderGroupConfig *readerGroupConfig,
+ UA_NodeId *readerGroupIdentifier) {
+ UA_StatusCode retval = UA_STATUSCODE_GOOD;
+
+ /* Check for valid readergroup configuration */
+ if(!readerGroupConfig)
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+
+ if(!readerGroupConfig->pubsubManagerCallback.addCustomCallback &&
+ readerGroupConfig->enableBlockingSocket) {
+ UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Adding ReaderGroup failed, blocking socket functionality "
+ "only supported in customcallback");
+ return UA_STATUSCODE_BADNOTSUPPORTED;
+ }
+
+ /* Search the connection by the given connectionIdentifier */
+ UA_PubSubConnection *currentConnectionContext =
+ UA_PubSubConnection_findConnectionbyId(server, connectionIdentifier);
+ if(!currentConnectionContext)
+ return UA_STATUSCODE_BADNOTFOUND;
+
+ if(currentConnectionContext->configurationFrozen){
+ UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Adding ReaderGroup failed. Subscriber configuration is frozen.");
+ return UA_STATUSCODE_BADCONFIGURATIONERROR;
+ }
+
+ /* Regist (bind) the connection channel if it is not already registered */
+ if(!currentConnectionContext->isRegistered) {
+ retval |= UA_PubSubConnection_regist(server, &connectionIdentifier);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+ }
+
+ /* Allocate memory for new reader group */
+ UA_ReaderGroup *newGroup = (UA_ReaderGroup *)UA_calloc(1, sizeof(UA_ReaderGroup));
+ if(!newGroup)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+
+ newGroup->componentType = UA_PUBSUB_COMPONENT_READERGROUP;
+ /* Generate nodeid for the readergroup identifier */
+ newGroup->linkedConnection = currentConnectionContext->identifier;
+
+ /* Deep copy of the config */
+ retval |= UA_ReaderGroupConfig_copy(readerGroupConfig, &newGroup->config);
+ /* Check user configured params and define it accordingly */
+ if(newGroup->config.subscribingInterval <= 0.0)
+ newGroup->config.subscribingInterval = 5; // Set default to 5 ms
+
+ if(newGroup->config.enableBlockingSocket)
+ newGroup->config.timeout = 0; // Set timeout to 0 for blocking socket
+
+ if((!newGroup->config.enableBlockingSocket) && (!newGroup->config.timeout))
+ newGroup->config.timeout = 1000; /* Set default to 1ms socket timeout
+ when non-blocking socket allows with
+ zero timeout */
+
+ LIST_INSERT_HEAD(&currentConnectionContext->readerGroups, newGroup, listEntry);
+ currentConnectionContext->readerGroupsSize++;
+
+#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL
+ retval |= addReaderGroupRepresentation(server, newGroup);
+#else
+ UA_PubSubManager_generateUniqueNodeId(&server->pubSubManager,
+ &newGroup->identifier);
+#endif
+ if(readerGroupIdentifier)
+ UA_NodeId_copy(&newGroup->identifier, readerGroupIdentifier);
+
+ return retval;
+}
+
+UA_StatusCode
+UA_Server_removeReaderGroup(UA_Server *server, UA_NodeId groupIdentifier) {
+ UA_ReaderGroup* readerGroup =
+ UA_ReaderGroup_findRGbyId(server, groupIdentifier);
+ if(readerGroup == NULL)
+ return UA_STATUSCODE_BADNOTFOUND;
+
+ if(readerGroup->configurationFrozen){
+ UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Remove ReaderGroup failed. Subscriber configuration is frozen.");
+ return UA_STATUSCODE_BADCONFIGURATIONERROR;
+ }
+
+ /* Search the connection to which the given readergroup is connected to */
+ UA_PubSubConnection *connection =
+ UA_PubSubConnection_findConnectionbyId(server, readerGroup->linkedConnection);
+ if(connection == NULL)
+ return UA_STATUSCODE_BADNOTFOUND;
+
+ /* Unregister subscribe callback */
+ if(readerGroup->state == UA_PUBSUBSTATE_OPERATIONAL)
+ UA_ReaderGroup_removeSubscribeCallback(server, readerGroup);
+
+#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL
+ removeReaderGroupRepresentation(server, readerGroup);
+#endif
+
+ /* UA_Server_ReaderGroup_clear also removes itself from the list */
+ UA_Server_ReaderGroup_clear(server, readerGroup);
+
+ /* Remove readerGroup from Connection */
+ LIST_REMOVE(readerGroup, listEntry);
+ UA_free(readerGroup);
+ return UA_STATUSCODE_GOOD;
+}
+
+/* TODO: Implement
+UA_StatusCode
+UA_Server_ReaderGroup_updateConfig(UA_Server *server, UA_NodeId readerGroupIdentifier,
+ const UA_ReaderGroupConfig *config) {
+ return UA_STATUSCODE_BADNOTIMPLEMENTED;
+}
+*/
+
+UA_StatusCode
+UA_Server_ReaderGroup_getConfig(UA_Server *server, UA_NodeId readerGroupIdentifier,
+ UA_ReaderGroupConfig *config) {
+ if(!config)
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+
+ /* Identify the readergroup through the readerGroupIdentifier */
+ UA_ReaderGroup *currentReaderGroup =
+ UA_ReaderGroup_findRGbyId(server, readerGroupIdentifier);
+ if(!currentReaderGroup)
+ return UA_STATUSCODE_BADNOTFOUND;
+
+ UA_ReaderGroupConfig tmpReaderGroupConfig;
+ /* deep copy of the actual config */
+ UA_ReaderGroupConfig_copy(&currentReaderGroup->config, &tmpReaderGroupConfig);
+ *config = tmpReaderGroupConfig;
+ return UA_STATUSCODE_GOOD;
+}
+
+static void
+UA_Server_ReaderGroup_clear(UA_Server* server, UA_ReaderGroup *readerGroup) {
+ UA_ReaderGroupConfig_clear(&readerGroup->config);
UA_DataSetReader *dataSetReader;
- retval = getReaderFromIdentifier(server, pMsg, &dataSetReader, pConnection);
- if(retval != UA_STATUSCODE_GOOD) {
- return retval;
+ UA_DataSetReader *tmpDataSetReader;
+ LIST_FOREACH_SAFE(dataSetReader, &readerGroup->readers, listEntry, tmpDataSetReader) {
+ UA_Server_removeDataSetReader(server, dataSetReader->identifier);
+ }
+ UA_PubSubConnection* pConn =
+ UA_PubSubConnection_findConnectionbyId(server, readerGroup->linkedConnection);
+ if(pConn != NULL)
+ pConn->readerGroupsSize--;
+
+ /* Delete ReaderGroup and its members */
+ UA_NodeId_clear(&readerGroup->linkedConnection);
+ UA_NodeId_clear(&readerGroup->identifier);
+
+#ifdef UA_ENABLE_PUBSUB_ENCRYPTION
+ if(readerGroup->config.securityPolicy && readerGroup->securityPolicyContext) {
+ readerGroup->config.securityPolicy->deleteContext(readerGroup->securityPolicyContext);
+ readerGroup->securityPolicyContext = NULL;
}
+#endif
+
+ UA_ReaderGroupConfig_clear(&readerGroup->config);
+}
+
+UA_StatusCode
+UA_Server_ReaderGroup_getState(UA_Server *server, UA_NodeId readerGroupIdentifier,
+ UA_PubSubState *state) {
+ if((server == NULL) || (state == NULL))
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+ UA_ReaderGroup *currentReaderGroup =
+ UA_ReaderGroup_findRGbyId(server, readerGroupIdentifier);
+ if(!currentReaderGroup)
+ return UA_STATUSCODE_BADNOTFOUND;
+ *state = currentReaderGroup->state;
+ return UA_STATUSCODE_GOOD;
+}
+
+/* ReaderGroup State */
+static UA_StatusCode
+UA_ReaderGroup_setPubSubState_disable(UA_Server *server,
+ UA_ReaderGroup *rg) {
+ UA_DataSetReader *dataSetReader;
+ switch(rg->state) {
+ case UA_PUBSUBSTATE_DISABLED:
+ return UA_STATUSCODE_GOOD;
+ case UA_PUBSUBSTATE_PAUSED:
+ break;
+ case UA_PUBSUBSTATE_OPERATIONAL:
+ UA_ReaderGroup_removeSubscribeCallback(server, rg);
+ LIST_FOREACH(dataSetReader, &rg->readers, listEntry) {
+ UA_DataSetReader_setPubSubState(server, UA_PUBSUBSTATE_DISABLED,
+ dataSetReader);
+ }
+ rg->state = UA_PUBSUBSTATE_DISABLED;
+ break;
+ case UA_PUBSUBSTATE_ERROR:
+ break;
+ default:
+ UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Unknown PubSub state!");
+ return UA_STATUSCODE_BADINTERNALERROR;
+ }
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_StatusCode
+UA_ReaderGroup_setPubSubState_paused(UA_Server *server,
+ UA_ReaderGroup *rg) {
UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER,
- "DataSetReader found with PublisherId");
+ "PubSub state paused is unsupported at the moment!");
+ switch(rg->state) {
+ case UA_PUBSUBSTATE_DISABLED:
+ break;
+ case UA_PUBSUBSTATE_PAUSED:
+ return UA_STATUSCODE_GOOD;
+ case UA_PUBSUBSTATE_OPERATIONAL:
+ break;
+ case UA_PUBSUBSTATE_ERROR:
+ break;
+ default:
+ UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Unknown PubSub state!");
+ return UA_STATUSCODE_BADINTERNALERROR;
+ }
+ return UA_STATUSCODE_BADNOTSUPPORTED;
+}
+
+static UA_StatusCode
+UA_ReaderGroup_setPubSubState_operational(UA_Server *server,
+ UA_ReaderGroup *rg) {
+ UA_DataSetReader *dataSetReader;
+ switch(rg->state) {
+ case UA_PUBSUBSTATE_DISABLED:
+ LIST_FOREACH(dataSetReader, &rg->readers, listEntry) {
+ UA_DataSetReader_setPubSubState(server, UA_PUBSUBSTATE_OPERATIONAL, dataSetReader);
+ }
+ UA_ReaderGroup_addSubscribeCallback(server, rg);
+ rg->state = UA_PUBSUBSTATE_OPERATIONAL;
+ return UA_STATUSCODE_GOOD;
+ case UA_PUBSUBSTATE_PAUSED:
+ break;
+ case UA_PUBSUBSTATE_OPERATIONAL:
+ return UA_STATUSCODE_GOOD;
+ case UA_PUBSUBSTATE_ERROR:
+ break;
+ default:
+ UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Unknown PubSub state!");
+ return UA_STATUSCODE_BADINTERNALERROR;
+ }
+ return UA_STATUSCODE_BADNOTSUPPORTED;
+}
+
+static UA_StatusCode
+UA_ReaderGroup_setPubSubState_error(UA_Server *server,
+ UA_ReaderGroup *rg) {
+ UA_DataSetReader *dataSetReader;
+ switch(rg->state) {
+ case UA_PUBSUBSTATE_DISABLED:
+ break;
+ case UA_PUBSUBSTATE_PAUSED:
+ break;
+ case UA_PUBSUBSTATE_OPERATIONAL:
+ UA_ReaderGroup_removeSubscribeCallback(server, rg);
+ LIST_FOREACH(dataSetReader, &rg->readers, listEntry){
+ UA_DataSetReader_setPubSubState(server, UA_PUBSUBSTATE_ERROR, dataSetReader);
+ }
+ break;
+ case UA_PUBSUBSTATE_ERROR:
+ return UA_STATUSCODE_GOOD;
+ default:
+ UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Unknown PubSub state!");
+ return UA_STATUSCODE_BADINTERNALERROR;
+ }
+ rg->state = UA_PUBSUBSTATE_ERROR;
+ return UA_STATUSCODE_GOOD;
+}
+
+UA_StatusCode
+UA_ReaderGroup_setPubSubState(UA_Server *server, UA_PubSubState state,
+ UA_ReaderGroup *readerGroup) {
+ switch(state) {
+ case UA_PUBSUBSTATE_DISABLED:
+ return UA_ReaderGroup_setPubSubState_disable(server, readerGroup);
+ case UA_PUBSUBSTATE_PAUSED:
+ return UA_ReaderGroup_setPubSubState_paused(server, readerGroup);
+ case UA_PUBSUBSTATE_OPERATIONAL:
+ return UA_ReaderGroup_setPubSubState_operational(server, readerGroup);
+ case UA_PUBSUBSTATE_ERROR:
+ return UA_ReaderGroup_setPubSubState_error(server, readerGroup);
+ default:
+ UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Received unknown PubSub state!");
+ break;
+ }
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+}
+
+UA_StatusCode
+UA_Server_setReaderGroupOperational(UA_Server *server, const UA_NodeId readerGroupId){
+ UA_ReaderGroup *rg = UA_ReaderGroup_findRGbyId(server, readerGroupId);
+ if(!rg)
+ return UA_STATUSCODE_BADNOTFOUND;
+ return UA_ReaderGroup_setPubSubState(server, UA_PUBSUBSTATE_OPERATIONAL, rg);
+}
+
+UA_StatusCode
+UA_Server_setReaderGroupDisabled(UA_Server *server, const UA_NodeId readerGroupId){
+ UA_ReaderGroup *rg = UA_ReaderGroup_findRGbyId(server, readerGroupId);
+ if(!rg)
+ return UA_STATUSCODE_BADNOTFOUND;
+ return UA_ReaderGroup_setPubSubState(server, UA_PUBSUBSTATE_DISABLED, rg);
+}
+
+#ifdef UA_ENABLE_PUBSUB_ENCRYPTION
+UA_StatusCode
+UA_Server_setReaderGroupEncryptionKeys(UA_Server *server, const UA_NodeId readerGroup,
+ UA_UInt32 securityTokenId,
+ const UA_ByteString signingKey,
+ const UA_ByteString encryptingKey,
+ const UA_ByteString keyNonce) {
+ UA_ReaderGroup *rg = UA_ReaderGroup_findRGbyId(server, readerGroup);
+ UA_CHECK_MEM(rg, return UA_STATUSCODE_BADNOTFOUND);
+
+ UA_CHECK_MEM_WARN(rg->config.securityPolicy, return UA_STATUSCODE_BADINTERNALERROR,
+ &server->config.logger, UA_LOGCATEGORY_SERVER,
+ "No SecurityPolicy configured for the ReaderGroup");
+
+ if(securityTokenId != rg->securityTokenId) {
+ rg->securityTokenId = securityTokenId;
+ rg->nonceSequenceNumber = 1;
+ }
+
+ /* Create a new context */
+ if(!rg->securityPolicyContext) {
+ return rg->config.securityPolicy->
+ newContext(rg->config.securityPolicy->policyContext,
+ &signingKey, &encryptingKey, &keyNonce,
+ &rg->securityPolicyContext);
+ }
+
+ /* Update the context */
+ return rg->config.securityPolicy->
+ setSecurityKeys(rg->securityPolicyContext, &signingKey,
+ &encryptingKey, &keyNonce);
+}
+#endif
+
+/* Freezing of the configuration */
+
+UA_StatusCode
+UA_Server_freezeReaderGroupConfiguration(UA_Server *server,
+ const UA_NodeId readerGroupId) {
+ UA_ReaderGroup *rg = UA_ReaderGroup_findRGbyId(server, readerGroupId);
+ if(!rg)
+ return UA_STATUSCODE_BADNOTFOUND;
+
+ /* PubSubConnection freezeCounter++ */
+ UA_NodeId pubSubConnectionId = rg->linkedConnection;
+ UA_PubSubConnection *pubSubConnection =
+ UA_PubSubConnection_findConnectionbyId(server, pubSubConnectionId);
+ pubSubConnection->configurationFreezeCounter++;
+ pubSubConnection->configurationFrozen = UA_TRUE;
+
+ /* ReaderGroup freeze */
+ /* TODO: Clarify on the freeze functionality in multiple DSR, multiple
+ * networkMessage conf in a RG */
+ rg->configurationFrozen = UA_TRUE;
+
+ /* DataSetReader freeze */
+ UA_DataSetReader *dataSetReader;
+ UA_UInt16 dsrCount = 0;
+ LIST_FOREACH(dataSetReader, &rg->readers, listEntry){
+ dataSetReader->configurationFrozen = UA_TRUE;
+ dsrCount++;
+ /* TODO: Configuration frozen for subscribedDataSet once
+ * UA_Server_DataSetReader_addTargetVariables API modified to support
+ * adding target variable one by one or in a group stored in a list. */
+ }
+
+ /* Not rt, we don't have to adjust anything */
+ if(rg->config.rtLevel != UA_PUBSUB_RT_FIXED_SIZE)
+ return UA_STATUSCODE_GOOD;
+
+ if(dsrCount > 1) {
+ UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Mutiple DSR in a readerGroup not supported in RT "
+ "fixed size configuration");
+ return UA_STATUSCODE_BADNOTIMPLEMENTED;
+ }
+
+ dataSetReader = LIST_FIRST(&rg->readers);
+
+ /* Support only to UADP encoding */
+ if(dataSetReader->config.messageSettings.content.decoded.type !=
+ &UA_TYPES[UA_TYPES_UADPDATASETREADERMESSAGEDATATYPE]) {
+ UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "PubSub-RT configuration fail: Non-RT capable encoding.");
+ return UA_STATUSCODE_BADNOTSUPPORTED;
+ }
+
+ size_t fieldsSize = dataSetReader->config.dataSetMetaData.fieldsSize;
+ for(size_t i = 0; i < fieldsSize; i++) {
+ UA_FieldTargetVariable *tv =
+ &dataSetReader->config.subscribedDataSet.subscribedDataSetTarget.targetVariables[i];
+ const UA_VariableNode *rtNode = (const UA_VariableNode *)
+ UA_NODESTORE_GET(server, &tv->targetVariable.targetNodeId);
+ if(rtNode != NULL &&
+ rtNode->valueBackend.backendType != UA_VALUEBACKENDTYPE_EXTERNAL) {
+ UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "PubSub-RT configuration fail: PDS contains field "
+ "without external data source.");
+ UA_NODESTORE_RELEASE(server, (const UA_Node *) rtNode);
+ return UA_STATUSCODE_BADNOTSUPPORTED;
+ }
- UA_Byte anzDataSets = 1;
- if(pMsg->payloadHeaderEnabled)
- anzDataSets = pMsg->payloadHeader.dataSetPayloadHeader.count;
- for(UA_Byte iterator = 0; iterator < anzDataSets; iterator++) {
- UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER, "Process Msg with DataSetReader!");
- UA_Server_DataSetReader_process(server, dataSetReader,
- &pMsg->payload.dataSetPayload.dataSetMessages[iterator]);
+ UA_NODESTORE_RELEASE(server, (const UA_Node *) rtNode);
+
+ UA_FieldMetaData *field = &dataSetReader->config.dataSetMetaData.fields[i];
+ if((UA_NodeId_equal(&field->dataType, &UA_TYPES[UA_TYPES_STRING].typeId) ||
+ UA_NodeId_equal(&field->dataType, &UA_TYPES[UA_TYPES_BYTESTRING].typeId)) &&
+ field->maxStringLength == 0) {
+ UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "PubSub-RT configuration fail: "
+ "PDS contains String/ByteString with dynamic length.");
+ return UA_STATUSCODE_BADNOTSUPPORTED;
+ } else if(!UA_DataType_isNumeric(UA_findDataType(&field->dataType)) &&
+ !UA_NodeId_equal(&field->dataType, &UA_TYPES[UA_TYPES_BOOLEAN].typeId)) {
+ UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "PubSub-RT configuration fail: "
+ "PDS contains variable with dynamic size.");
+ return UA_STATUSCODE_BADNOTSUPPORTED;
+ }
}
- /* To Do Handle when dataSetReader parameters are null for publisherId
- * and zero for WriterGroupId and DataSetWriterId */
+ UA_DataSetMessage *dsm = (UA_DataSetMessage *) UA_calloc(1, sizeof(UA_DataSetMessage));
+ if(!dsm) {
+ UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "PubSub RT Offset calculation: DSM creation failed");
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ }
+
+ /* Generate the DSM */
+ UA_StatusCode res = UA_DataSetReader_generateDataSetMessage(server, dsm, dataSetReader);
+ if(res != UA_STATUSCODE_GOOD) {
+ UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "PubSub RT Offset calculation: DataSetMessage generation failed");
+ UA_DataSetMessage_clear(dsm);
+ UA_free(dsm);
+ return UA_STATUSCODE_BADINTERNALERROR;
+ }
+
+ /* Generate data set messages - Considering 1 DSM as max */
+ UA_UInt16 *dsWriterIds = (UA_UInt16 *)UA_calloc(1, sizeof(UA_UInt16));
+ if(!dsWriterIds) {
+ UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "PubSub RT Offset calculation: DataSetWriterId creation failed");
+ UA_DataSetMessage_clear(dsm);
+ UA_free(dsm);
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ }
+ *dsWriterIds = dataSetReader->config.dataSetWriterId;
+
+ UA_NetworkMessage *networkMessage = (UA_NetworkMessage *)UA_calloc(1, sizeof(UA_NetworkMessage));
+ if(!networkMessage) {
+ UA_free(dsWriterIds);
+ UA_DataSetMessage_clear(dsm);
+ UA_free(dsm);
+ UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "PubSub RT Offset calculation: Network message creation failed");
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ }
+
+ res = UA_DataSetReader_generateNetworkMessage(pubSubConnection, dataSetReader, dsm,
+ dsWriterIds, 1, networkMessage);
+ if(res != UA_STATUSCODE_GOOD) {
+ UA_free(networkMessage->payload.dataSetPayload.sizes);
+ UA_free(networkMessage);
+ UA_free(dsWriterIds);
+ UA_DataSetMessage_clear(dsm);
+ UA_free(dsm);
+ UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "PubSub RT Offset calculation: NetworkMessage generation failed");
+ return UA_STATUSCODE_BADINTERNALERROR;
+ }
+
+ memset(&dataSetReader->bufferedMessage, 0, sizeof(UA_NetworkMessageOffsetBuffer));
+ dataSetReader->bufferedMessage.RTsubscriberEnabled = true;
+
+ /* Fix the offsets necessary to decode */
+ UA_NetworkMessage_calcSizeBinary(networkMessage, &dataSetReader->bufferedMessage);
+ dataSetReader->bufferedMessage.nm = networkMessage;
+
return UA_STATUSCODE_GOOD;
}
+UA_StatusCode
+UA_Server_unfreezeReaderGroupConfiguration(UA_Server *server,
+ const UA_NodeId readerGroupId) {
+ UA_ReaderGroup *rg = UA_ReaderGroup_findRGbyId(server, readerGroupId);
+ if(!rg)
+ return UA_STATUSCODE_BADNOTFOUND;
+
+ /* PubSubConnection freezeCounter-- */
+ UA_NodeId pubSubConnectionId = rg->linkedConnection;
+ UA_PubSubConnection *pubSubConnection =
+ UA_PubSubConnection_findConnectionbyId(server, pubSubConnectionId);
+ pubSubConnection->configurationFreezeCounter--;
+ if(pubSubConnection->configurationFreezeCounter == 0){
+ pubSubConnection->configurationFrozen = UA_FALSE;
+ }
+
+ /* ReaderGroup unfreeze */
+ rg->configurationFrozen = UA_FALSE;
+
+ /* DataSetReader unfreeze */
+ UA_DataSetReader *dataSetReader;
+ LIST_FOREACH(dataSetReader, &rg->readers, listEntry) {
+ dataSetReader->configurationFrozen = UA_FALSE;
+ }
+
+ if(rg->config.rtLevel != UA_PUBSUB_RT_FIXED_SIZE)
+ return UA_STATUSCODE_GOOD;
+
+ dataSetReader = LIST_FIRST(&rg->readers);
+ if(dataSetReader->bufferedMessage.offsetsSize > 0) {
+ for(size_t i = 0; i < dataSetReader->bufferedMessage.offsetsSize; i++) {
+ UA_NetworkMessageOffset *offset = &dataSetReader->bufferedMessage.offsets[i];
+ if((offset->contentType == UA_PUBSUB_OFFSETTYPE_PAYLOAD_VARIANT) ||
+ (offset->contentType == UA_PUBSUB_OFFSETTYPE_PAYLOAD_RAW)) {
+ UA_DataValue_delete(offset->offsetData.value.value);
+ } else if(offset->contentType == UA_PUBSUB_OFFSETTYPE_NETWORKMESSAGE_FIELDENCDODING) {
+ offset->offsetData.value.value->value.data = NULL;
+ UA_DataValue_delete(offset->offsetData.value.value);
+ }
+ }
+ UA_free(dataSetReader->bufferedMessage.offsets);
+ }
+
+ if(dataSetReader->bufferedMessage.RTsubscriberEnabled &&
+ dataSetReader->bufferedMessage.nm) {
+ UA_NetworkMessage_delete(dataSetReader->bufferedMessage.nm);
+ UA_free(dataSetReader->bufferedMessage.nm);
+ }
+
+ return UA_STATUSCODE_GOOD;
+}
+
+/* This triggers the collection and reception of NetworkMessages and the
+ * contained DataSetMessages. */
+void
+UA_ReaderGroup_subscribeCallback(UA_Server *server,
+ UA_ReaderGroup *readerGroup) {
+ // TODO: feedback for debug-assert vs runtime-check
+ UA_assert(server);
+ UA_assert(readerGroup);
+
+ UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "PubSub subscribe callback");
+
+ UA_PubSubConnection *connection =
+ UA_PubSubConnection_findConnectionbyId(server, readerGroup->linkedConnection);
+ if(!connection) {
+ UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "SubscribeCallback(): Find linked connection failed");
+ UA_ReaderGroup_setPubSubState(server, UA_PUBSUBSTATE_ERROR, readerGroup);
+ return;
+ }
+
+ receiveBufferedNetworkMessage(server, readerGroup, connection);
+}
+
+/* Add new subscribeCallback. The first execution is triggered directly after
+ * creation. */
+UA_StatusCode
+UA_ReaderGroup_addSubscribeCallback(UA_Server *server, UA_ReaderGroup *readerGroup) {
+ UA_StatusCode retval = UA_STATUSCODE_GOOD;
+ if(readerGroup->config.pubsubManagerCallback.addCustomCallback)
+ retval = readerGroup->config.pubsubManagerCallback.
+ addCustomCallback(server, readerGroup->identifier,
+ (UA_ServerCallback)UA_ReaderGroup_subscribeCallback,
+ readerGroup, readerGroup->config.subscribingInterval,
+ NULL, // TODO: Send base time from reader group config
+ // TODO: Send timer policy from reader group config
+ UA_TIMER_HANDLE_CYCLEMISS_WITH_CURRENTTIME,
+ &readerGroup->subscribeCallbackId);
+ else {
+ if(readerGroup->config.enableBlockingSocket == UA_TRUE) {
+ UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "addSubscribeCallback() failed, blocking socket "
+ "functionality only supported in customcallback");
+ return UA_STATUSCODE_BADNOTSUPPORTED;
+ }
+
+ retval = UA_PubSubManager_addRepeatedCallback(server,
+ (UA_ServerCallback)UA_ReaderGroup_subscribeCallback,
+ readerGroup, readerGroup->config.subscribingInterval,
+ NULL, // TODO: Send base time from reader group config
+ // TODO: Send timer policy from reader group config
+ UA_TIMER_HANDLE_CYCLEMISS_WITH_CURRENTTIME,
+ &readerGroup->subscribeCallbackId);
+ }
+
+ /* Run once after creation */
+ /* When using blocking socket functionality, the server mechanism might get
+ * blocked. It is highly recommended to use custom callback when using
+ * blockingsocket. */
+ if(readerGroup->config.enableBlockingSocket != UA_TRUE)
+ UA_ReaderGroup_subscribeCallback(server, readerGroup);
+
+ return retval;
+}
+
+void
+UA_ReaderGroup_removeSubscribeCallback(UA_Server *server, UA_ReaderGroup *readerGroup) {
+ if(readerGroup->config.pubsubManagerCallback.removeCustomCallback)
+ readerGroup->config.pubsubManagerCallback.
+ removeCustomCallback(server, readerGroup->identifier,
+ readerGroup->subscribeCallbackId);
+ else
+ UA_PubSubManager_removeRepeatedPubSubCallback(server,
+ readerGroup->subscribeCallbackId);
+}
+
#endif /* UA_ENABLE_PUBSUB */
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/src/pubsub/ua_pubsub_manager.c" ***********************************/
+/**** amalgamated original file "/src/pubsub/ua_pubsub_manager.c" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -30899,6 +32540,7 @@ UA_Server_processNetworkMessage(UA_Server *server, UA_NetworkMessage *pMsg,
#ifdef UA_ENABLE_PUBSUB /* conditional compilation */
+
#define UA_DATETIMESTAMP_2000 125911584000000000
UA_StatusCode
@@ -30907,11 +32549,11 @@ UA_Server_addPubSubConnection(UA_Server *server,
UA_NodeId *connectionIdentifier) {
/* Find the matching UA_PubSubTransportLayers */
UA_PubSubTransportLayer *tl = NULL;
- for(size_t i = 0; i < server->config.pubsubTransportLayersSize; i++) {
+ for(size_t i = 0; i < server->config.pubSubConfig.transportLayersSize; i++) {
if(connectionConfig &&
- UA_String_equal(&server->config.pubsubTransportLayers[i].transportProfileUri,
+ UA_String_equal(&server->config.pubSubConfig.transportLayers[i].transportProfileUri,
&connectionConfig->transportProfileUri)) {
- tl = &server->config.pubsubTransportLayers[i];
+ tl = &server->config.pubSubConfig.transportLayers[i];
}
}
if(!tl) {
@@ -30946,6 +32588,7 @@ UA_Server_addPubSubConnection(UA_Server *server,
"PubSub Connection creation failed. Out of Memory.");
return UA_STATUSCODE_BADOUTOFMEMORY;
}
+ newConnectionsField->componentType = UA_PUBSUB_COMPONENT_CONNECTION;
if (server->pubSubManager.connectionsSize != 0)
TAILQ_INSERT_TAIL(&server->pubSubManager.connections, newConnectionsField, listEntry);
else {
@@ -30970,14 +32613,18 @@ UA_Server_addPubSubConnection(UA_Server *server,
return UA_STATUSCODE_BADINTERNALERROR;
}
- UA_PubSubManager_generateUniqueNodeId(server, &newConnectionsField->identifier);
+#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL
+ /* Internally createa a unique id */
+ addPubSubConnectionRepresentation(server, newConnectionsField);
+#else
+ /* Create a unique NodeId that does not correspond to a Node */
+ UA_PubSubManager_generateUniqueNodeId(&server->pubSubManager,
+ &newConnectionsField->identifier);
+#endif
if(connectionIdentifier)
UA_NodeId_copy(&newConnectionsField->identifier, connectionIdentifier);
-#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL
- addPubSubConnectionRepresentation(server, newConnectionsField);
-#endif
return UA_STATUSCODE_GOOD;
}
@@ -30999,8 +32646,30 @@ UA_Server_removePubSubConnection(UA_Server *server, const UA_NodeId connection)
return UA_STATUSCODE_GOOD;
}
+UA_StatusCode
+UA_PubSubConnection_regist(UA_Server *server, UA_NodeId *connectionIdentifier) {
+ UA_PubSubConnection *connection =
+ UA_PubSubConnection_findConnectionbyId(server, *connectionIdentifier);
+ if(!connection)
+ return UA_STATUSCODE_BADNOTFOUND;
+
+ if(connection->isRegistered) {
+ UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_SERVER, "Connection already registered");
+ return UA_STATUSCODE_GOOD;
+ }
+
+ UA_StatusCode retval = connection->channel->regist(connection->channel, NULL, NULL);
+ if(retval != UA_STATUSCODE_GOOD)
+ UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "register channel failed: 0x%" PRIx32 "!", retval);
+
+ connection->isRegistered = UA_TRUE;
+ return retval;
+}
+
UA_AddPublishedDataSetResult
-UA_Server_addPublishedDataSet(UA_Server *server, const UA_PublishedDataSetConfig *publishedDataSetConfig,
+UA_Server_addPublishedDataSet(UA_Server *server,
+ const UA_PublishedDataSetConfig *publishedDataSetConfig,
UA_NodeId *pdsIdentifier) {
UA_AddPublishedDataSetResult result = {UA_STATUSCODE_BADINVALIDARGUMENT, 0, NULL, {0, 0}};
if(!publishedDataSetConfig){
@@ -31008,97 +32677,96 @@ UA_Server_addPublishedDataSet(UA_Server *server, const UA_PublishedDataSetConfig
"PublishedDataSet creation failed. No config passed in.");
return result;
}
+
if(publishedDataSetConfig->publishedDataSetType != UA_PUBSUB_DATASET_PUBLISHEDITEMS){
UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
"PublishedDataSet creation failed. Unsupported PublishedDataSet type.");
return result;
}
- //deep copy the given connection config
- UA_PublishedDataSetConfig tmpPublishedDataSetConfig;
- memset(&tmpPublishedDataSetConfig, 0, sizeof(UA_PublishedDataSetConfig));
- if(UA_PublishedDataSetConfig_copy(publishedDataSetConfig, &tmpPublishedDataSetConfig) != UA_STATUSCODE_GOOD){
- UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
- "PublishedDataSet creation failed. Configuration copy failed.");
- result.addResult = UA_STATUSCODE_BADINTERNALERROR;
- return result;
- }
- //create new PDS and add to UA_PubSubManager
- UA_PublishedDataSet *newPubSubDataSetField = (UA_PublishedDataSet *)
- UA_calloc(1, sizeof(UA_PublishedDataSet));
- if(!newPubSubDataSetField) {
- UA_PublishedDataSetConfig_clear(&tmpPublishedDataSetConfig);
+
+ /* Create new PDS and add to UA_PubSubManager */
+ UA_PublishedDataSet *newPDS = (UA_PublishedDataSet *)
+ UA_calloc(1, sizeof(UA_PublishedDataSet));
+ if(!newPDS) {
UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
"PublishedDataSet creation failed. Out of Memory.");
result.addResult = UA_STATUSCODE_BADOUTOFMEMORY;
return result;
}
- memset(newPubSubDataSetField, 0, sizeof(UA_PublishedDataSet));
- TAILQ_INIT(&newPubSubDataSetField->fields);
- newPubSubDataSetField->config = tmpPublishedDataSetConfig;
+ TAILQ_INIT(&newPDS->fields);
- if (server->pubSubManager.publishedDataSetsSize != 0)
- TAILQ_INSERT_TAIL(&server->pubSubManager.publishedDataSets, newPubSubDataSetField, listEntry);
- else {
- TAILQ_INIT(&server->pubSubManager.publishedDataSets);
- TAILQ_INSERT_HEAD(&server->pubSubManager.publishedDataSets, newPubSubDataSetField, listEntry);
- }
- if(tmpPublishedDataSetConfig.publishedDataSetType == UA_PUBSUB_DATASET_PUBLISHEDITEMS_TEMPLATE){
- //parse template config and add fields (later PubSub batch)
+ UA_PublishedDataSetConfig *newConfig = &newPDS->config;
+
+ /* Deep copy the given connection config */
+ UA_StatusCode res = UA_PublishedDataSetConfig_copy(publishedDataSetConfig, newConfig);
+ if(res != UA_STATUSCODE_GOOD){
+ UA_free(newPDS);
+ UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "PublishedDataSet creation failed. Configuration copy failed.");
+ result.addResult = UA_STATUSCODE_BADINTERNALERROR;
+ return result;
}
- //generate unique nodeId
- UA_PubSubManager_generateUniqueNodeId(server, &newPubSubDataSetField->identifier);
- if(pdsIdentifier != NULL){
- UA_NodeId_copy(&newPubSubDataSetField->identifier, pdsIdentifier);
+
+ /* TODO: Parse template config and add fields (later PubSub batch) */
+ if(newConfig->publishedDataSetType == UA_PUBSUB_DATASET_PUBLISHEDITEMS_TEMPLATE) {
}
- result.addResult = UA_STATUSCODE_GOOD;
- result.fieldAddResults = NULL;
- result.fieldAddResultsSize = 0;
+ /* Fill the DataSetMetaData */
+ result.configurationVersion.majorVersion = UA_PubSubConfigurationVersionTimeDifference();
+ result.configurationVersion.minorVersion = UA_PubSubConfigurationVersionTimeDifference();
+ switch(newConfig->publishedDataSetType) {
+ case UA_PUBSUB_DATASET_PUBLISHEDEVENTS_TEMPLATE:
+ res = UA_STATUSCODE_BADNOTSUPPORTED;
+ break;
+ case UA_PUBSUB_DATASET_PUBLISHEDEVENTS:
+ res = UA_STATUSCODE_BADNOTSUPPORTED;
+ break;
+ case UA_PUBSUB_DATASET_PUBLISHEDITEMS:
+ newPDS->dataSetMetaData.configurationVersion.majorVersion =
+ UA_PubSubConfigurationVersionTimeDifference();
+ newPDS->dataSetMetaData.configurationVersion.minorVersion =
+ UA_PubSubConfigurationVersionTimeDifference();
+ newPDS->dataSetMetaData.description = UA_LOCALIZEDTEXT_ALLOC("", "");
+ newPDS->dataSetMetaData.dataSetClassId = UA_GUID_NULL;
+ res = UA_String_copy(&newConfig->name, &newPDS->dataSetMetaData.name);
+ break;
+ case UA_PUBSUB_DATASET_PUBLISHEDITEMS_TEMPLATE:
+ res = UA_DataSetMetaDataType_copy(&newConfig->config.itemsTemplate.metaData,
+ &newPDS->dataSetMetaData);
+ break;
+ default:
+ res = UA_STATUSCODE_BADINTERNALERROR;
+ }
- //fill the DataSetMetaData
- switch(tmpPublishedDataSetConfig.publishedDataSetType){
- case UA_PUBSUB_DATASET_PUBLISHEDITEMS_TEMPLATE:
- if(UA_DataSetMetaDataType_copy(&tmpPublishedDataSetConfig.config.itemsTemplate.metaData,
- &newPubSubDataSetField->dataSetMetaData) != UA_STATUSCODE_GOOD){
- UA_Server_removeDataSetField(server, newPubSubDataSetField->identifier);
- result.addResult = UA_STATUSCODE_BADINTERNALERROR;
- }
- break;
- case UA_PUBSUB_DATASET_PUBLISHEDEVENTS_TEMPLATE:
- if(UA_DataSetMetaDataType_copy(&tmpPublishedDataSetConfig.config.eventTemplate.metaData,
- &newPubSubDataSetField->dataSetMetaData) != UA_STATUSCODE_GOOD){
- UA_Server_removeDataSetField(server, newPubSubDataSetField->identifier);
- result.addResult = UA_STATUSCODE_BADINTERNALERROR;
- }
- break;
- case UA_PUBSUB_DATASET_PUBLISHEDEVENTS:
- newPubSubDataSetField->dataSetMetaData.configurationVersion.majorVersion = UA_PubSubConfigurationVersionTimeDifference();
- newPubSubDataSetField->dataSetMetaData.configurationVersion.minorVersion = UA_PubSubConfigurationVersionTimeDifference();
- newPubSubDataSetField->dataSetMetaData.dataSetClassId = UA_GUID_NULL;
- if(UA_String_copy(&tmpPublishedDataSetConfig.name, &newPubSubDataSetField->dataSetMetaData.name) != UA_STATUSCODE_GOOD){
- UA_Server_removeDataSetField(server, newPubSubDataSetField->identifier);
- result.addResult = UA_STATUSCODE_BADINTERNALERROR;
- }
- newPubSubDataSetField->dataSetMetaData.description = UA_LOCALIZEDTEXT_ALLOC("", "");
- break;
- case UA_PUBSUB_DATASET_PUBLISHEDITEMS:
- newPubSubDataSetField->dataSetMetaData.configurationVersion.majorVersion = UA_PubSubConfigurationVersionTimeDifference();
- newPubSubDataSetField->dataSetMetaData.configurationVersion.minorVersion = UA_PubSubConfigurationVersionTimeDifference();
- if(UA_String_copy(&tmpPublishedDataSetConfig.name, &newPubSubDataSetField->dataSetMetaData.name) != UA_STATUSCODE_GOOD){
- UA_Server_removeDataSetField(server, newPubSubDataSetField->identifier);
- result.addResult = UA_STATUSCODE_BADINTERNALERROR;
- }
- newPubSubDataSetField->dataSetMetaData.description = UA_LOCALIZEDTEXT_ALLOC("", "");
- newPubSubDataSetField->dataSetMetaData.dataSetClassId = UA_GUID_NULL;
- break;
+ /* Abort? */
+ result.addResult = res;
+ if(result.addResult != UA_STATUSCODE_GOOD) {
+ UA_PublishedDataSetConfig_clear(newConfig);
+ UA_free(newPDS);
+ return result;
}
+ /* Insert into the queue of the manager */
+ if(server->pubSubManager.publishedDataSetsSize != 0) {
+ TAILQ_INSERT_TAIL(&server->pubSubManager.publishedDataSets,
+ newPDS, listEntry);
+ } else {
+ TAILQ_INIT(&server->pubSubManager.publishedDataSets);
+ TAILQ_INSERT_HEAD(&server->pubSubManager.publishedDataSets,
+ newPDS, listEntry);
+ }
server->pubSubManager.publishedDataSetsSize++;
- result.configurationVersion.majorVersion = UA_PubSubConfigurationVersionTimeDifference();
- result.configurationVersion.minorVersion = UA_PubSubConfigurationVersionTimeDifference();
+
#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL
- addPublishedDataItemsRepresentation(server, newPubSubDataSetField);
+ /* Create representation and unique id */
+ addPublishedDataItemsRepresentation(server, newPDS);
+#else
+ /* Generate unique nodeId */
+ UA_PubSubManager_generateUniqueNodeId(&server->pubSubManager, &newPDS->identifier);
#endif
+ if(pdsIdentifier)
+ UA_NodeId_copy(&newPDS->identifier, pdsIdentifier);
+
return result;
}
@@ -31109,7 +32777,7 @@ UA_Server_removePublishedDataSet(UA_Server *server, const UA_NodeId pds) {
if(!publishedDataSet){
return UA_STATUSCODE_BADNOTFOUND;
}
- if(publishedDataSet->config.configurationFrozen){
+ if(publishedDataSet->configurationFrozen){
UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
"Remove PublishedDataSet failed. PublishedDataSet is frozen.");
return UA_STATUSCODE_BADCONFIGURATIONERROR;
@@ -31142,19 +32810,29 @@ UA_Server_removePublishedDataSet(UA_Server *server, const UA_NodeId pds) {
/* Calculate the time difference between current time and UTC (00:00) on January
* 1, 2000. */
UA_UInt32
-UA_PubSubConfigurationVersionTimeDifference() {
+UA_PubSubConfigurationVersionTimeDifference(void) {
UA_UInt32 timeDiffSince2000 = (UA_UInt32) (UA_DateTime_now() - UA_DATETIMESTAMP_2000);
return timeDiffSince2000;
}
/* Generate a new unique NodeId. This NodeId will be used for the information
* model representation of PubSub entities. */
+#ifndef UA_ENABLE_PUBSUB_INFORMATIONMODEL
void
-UA_PubSubManager_generateUniqueNodeId(UA_Server *server, UA_NodeId *nodeId) {
- UA_NodeId newNodeId = UA_NODEID_NUMERIC(0, 0);
- UA_Node *newNode = UA_NODESTORE_NEW(server, UA_NODECLASS_OBJECT);
- UA_NODESTORE_INSERT(server, newNode, &newNodeId);
- UA_NodeId_copy(&newNodeId, nodeId);
+UA_PubSubManager_generateUniqueNodeId(UA_PubSubManager *psm, UA_NodeId *nodeId) {
+ *nodeId = UA_NODEID_NUMERIC(1, ++psm->uniqueIdCount);
+}
+#endif
+
+UA_Guid
+UA_PubSubManager_generateUniqueGuid(UA_Server *server) {
+ while(true) {
+ UA_NodeId testId = UA_NODEID_GUID(1, UA_Guid_random());
+ const UA_Node *testNode = UA_NODESTORE_GET(server, &testId);
+ if(!testNode)
+ return testId.identifier.guid;
+ UA_NODESTORE_RELEASE(server, testNode);
+ }
}
/* Delete the current PubSub configuration including all nested members. This
@@ -31176,9 +32854,9 @@ UA_PubSubManager_delete(UA_Server *server, UA_PubSubManager *pubSubManager) {
}
//free the currently configured transport layers
- if (server->config.pubsubTransportLayersSize > 0) {
- UA_free(server->config.pubsubTransportLayers);
- server->config.pubsubTransportLayersSize = 0;
+ if(server->config.pubSubConfig.transportLayersSize > 0) {
+ UA_free(server->config.pubSubConfig.transportLayers);
+ server->config.pubSubConfig.transportLayersSize = 0;
}
//remove Connections and WriterGroups
@@ -31196,22 +32874,21 @@ UA_PubSubManager_delete(UA_Server *server, UA_PubSubManager *pubSubManager) {
/* PubSub Jobs abstraction */
/***********************************/
-#ifndef UA_ENABLE_PUBSUB_CUSTOM_PUBLISH_HANDLING
-
-/* If UA_ENABLE_PUBSUB_CUSTOM_PUBLISH_HANDLING is enabled, a custom callback
- * management must be linked to the application */
+/* Default Timer based PubSub Callbacks */
UA_StatusCode
UA_PubSubManager_addRepeatedCallback(UA_Server *server, UA_ServerCallback callback,
- void *data, UA_Double interval_ms, UA_UInt64 *callbackId) {
+ void *data, UA_Double interval_ms, UA_DateTime *baseTime,
+ UA_TimerPolicy timerPolicy, UA_UInt64 *callbackId) {
return UA_Timer_addRepeatedCallback(&server->timer, (UA_ApplicationCallback)callback,
- server, data, interval_ms, callbackId);
+ server, data, interval_ms, baseTime, timerPolicy, callbackId);
}
UA_StatusCode
-UA_PubSubManager_changeRepeatedCallbackInterval(UA_Server *server, UA_UInt64 callbackId,
- UA_Double interval_ms) {
- return UA_Timer_changeRepeatedCallbackInterval(&server->timer, callbackId, interval_ms);
+UA_PubSubManager_changeRepeatedCallback(UA_Server *server, UA_UInt64 callbackId,
+ UA_Double interval_ms, UA_DateTime *baseTime,
+ UA_TimerPolicy timerPolicy) {
+ return UA_Timer_changeRepeatedCallback(&server->timer, callbackId, interval_ms, baseTime, timerPolicy);
}
void
@@ -31219,65 +32896,264 @@ UA_PubSubManager_removeRepeatedPubSubCallback(UA_Server *server, UA_UInt64 callb
UA_Timer_removeCallback(&server->timer, callbackId);
}
-#endif /* UA_ENABLE_PUBSUB_CUSTOM_PUBLISH_HANDLING */
+
+#ifdef UA_ENABLE_PUBSUB_MONITORING
+
+static UA_StatusCode
+UA_PubSubComponent_createMonitoring(UA_Server *server, UA_NodeId Id, UA_PubSubComponentEnumType eComponentType,
+ UA_PubSubMonitoringType eMonitoringType, void *data, UA_ServerCallback callback) {
+
+ if ((!server) || (!data)) {
+ UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER, "Error UA_PubSubComponent_createMonitoring(): "
+ "null pointer param");
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+ }
+ UA_StatusCode ret = UA_STATUSCODE_GOOD;
+ switch (eComponentType) {
+ case UA_PUBSUB_COMPONENT_DATASETREADER: {
+ UA_DataSetReader *reader = (UA_DataSetReader*) data;
+ switch (eMonitoringType) {
+ case UA_PUBSUB_MONITORING_MESSAGE_RECEIVE_TIMEOUT:
+ UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER, "UA_PubSubComponent_createMonitoring(): DataSetReader '%.*s' "
+ "- MessageReceiveTimeout", (UA_Int32) reader->config.name.length, reader->config.name.data);
+ reader->msgRcvTimeoutTimerCallback = callback;
+ break;
+ default:
+ UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER, "UA_PubSubComponent_createMonitoring(): DataSetReader '%.*s' "
+ "DataSetReader does not support timeout type '%i'", (UA_Int32) reader->config.name.length, reader->config.name.data,
+ eMonitoringType);
+ ret = UA_STATUSCODE_BADNOTSUPPORTED;
+ break;
+ }
+ break;
+ }
+ default:
+ UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Error UA_PubSubComponent_createMonitoring(): PubSub component type '%i' is not supported", eComponentType);
+ ret = UA_STATUSCODE_BADNOTSUPPORTED;
+ break;
+ }
+ return ret;
+}
+
+static UA_StatusCode
+UA_PubSubComponent_startMonitoring(UA_Server *server, UA_NodeId Id, UA_PubSubComponentEnumType eComponentType,
+ UA_PubSubMonitoringType eMonitoringType, void *data) {
+
+ if ((!server) || (!data)) {
+ UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER, "Error UA_PubSubComponent_startMonitoring(): "
+ "null pointer param");
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+ }
+
+ UA_StatusCode ret = UA_STATUSCODE_GOOD;
+ switch (eComponentType) {
+ case UA_PUBSUB_COMPONENT_DATASETREADER: {
+ UA_DataSetReader *reader = (UA_DataSetReader*) data;
+ switch (eMonitoringType) {
+ case UA_PUBSUB_MONITORING_MESSAGE_RECEIVE_TIMEOUT: {
+ /* use a timed callback, because one notification is enough,
+ we assume that MessageReceiveTimeout configuration is in [ms], we do not handle or check fractions */
+ UA_UInt64 interval = (UA_UInt64)(reader->config.messageReceiveTimeout * UA_DATETIME_MSEC);
+ ret = UA_Timer_addTimedCallback(&server->timer, (UA_ApplicationCallback) reader->msgRcvTimeoutTimerCallback,
+ server, reader, UA_DateTime_nowMonotonic() + (UA_DateTime) interval, &(reader->msgRcvTimeoutTimerId));
+ if (ret == UA_STATUSCODE_GOOD) {
+ UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "UA_PubSubComponent_startMonitoring(): DataSetReader '%.*s'- MessageReceiveTimeout: MessageReceiveTimeout = '%f' "
+ "Timer Id = '%u'", (UA_Int32) reader->config.name.length, reader->config.name.data,
+ reader->config.messageReceiveTimeout, (UA_UInt32) reader->msgRcvTimeoutTimerId);
+ } else {
+ UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Error UA_PubSubComponent_startMonitoring(): DataSetReader '%.*s' - MessageReceiveTimeout: start timer failed",
+ (UA_Int32) reader->config.name.length, reader->config.name.data);
+ }
+ break;
+ }
+ default:
+ UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER, "UA_PubSubComponent_startMonitoring(): DataSetReader '%.*s' "
+ "DataSetReader does not support timeout type '%i'", (UA_Int32) reader->config.name.length, reader->config.name.data,
+ eMonitoringType);
+ ret = UA_STATUSCODE_BADNOTSUPPORTED;
+ break;
+ }
+ break;
+ }
+ default:
+ UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Error UA_PubSubComponent_startMonitoring(): PubSub component type '%i' is not supported", eComponentType);
+ ret = UA_STATUSCODE_BADNOTSUPPORTED;
+ break;
+ }
+ return ret;
+}
+
+static UA_StatusCode
+UA_PubSubComponent_stopMonitoring(UA_Server *server, UA_NodeId Id, UA_PubSubComponentEnumType eComponentType,
+ UA_PubSubMonitoringType eMonitoringType, void *data) {
+
+ if ((!server) || (!data)) {
+ UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER, "Error UA_PubSubComponent_stopMonitoring(): "
+ "null pointer param");
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+ }
+
+ UA_StatusCode ret = UA_STATUSCODE_GOOD;
+ switch (eComponentType) {
+ case UA_PUBSUB_COMPONENT_DATASETREADER: {
+ UA_DataSetReader *reader = (UA_DataSetReader*) data;
+ switch (eMonitoringType) {
+ case UA_PUBSUB_MONITORING_MESSAGE_RECEIVE_TIMEOUT: {
+ UA_Timer_removeCallback(&server->timer, reader->msgRcvTimeoutTimerId);
+ UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "UA_PubSubComponent_stopMonitoring(): DataSetReader '%.*s' - MessageReceiveTimeout: MessageReceiveTimeout = '%f' "
+ "Timer Id = '%u'", (UA_Int32) reader->config.name.length, reader->config.name.data,
+ reader->config.messageReceiveTimeout, (UA_UInt32) reader->msgRcvTimeoutTimerId);
+ break;
+ }
+ default:
+ UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER, "UA_PubSubComponent_stopMonitoring(): DataSetReader '%.*s' "
+ "DataSetReader does not support timeout type '%i'", (UA_Int32) reader->config.name.length, reader->config.name.data,
+ eMonitoringType);
+ ret = UA_STATUSCODE_BADNOTSUPPORTED;
+ break;
+ }
+ break;
+ }
+ default:
+ UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Error UA_PubSubComponent_stopMonitoring(): PubSub component type '%i' is not supported", eComponentType);
+ ret = UA_STATUSCODE_BADNOTSUPPORTED;
+ break;
+ }
+ return ret;
+}
+
+static UA_StatusCode
+UA_PubSubComponent_updateMonitoringInterval(UA_Server *server, UA_NodeId Id, UA_PubSubComponentEnumType eComponentType,
+ UA_PubSubMonitoringType eMonitoringType, void *data)
+{
+ if ((!server) || (!data)) {
+ UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER, "Error UA_PubSubComponent_updateMonitoringInterval(): "
+ "null pointer param");
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+ }
+ UA_StatusCode ret = UA_STATUSCODE_GOOD;
+ switch (eComponentType) {
+ case UA_PUBSUB_COMPONENT_DATASETREADER: {
+ UA_DataSetReader *reader = (UA_DataSetReader*) data;
+ switch (eMonitoringType) {
+ case UA_PUBSUB_MONITORING_MESSAGE_RECEIVE_TIMEOUT: {
+ ret = UA_Timer_changeRepeatedCallback(&server->timer, reader->msgRcvTimeoutTimerId,
+ reader->config.messageReceiveTimeout, NULL,
+ UA_TIMER_HANDLE_CYCLEMISS_WITH_CURRENTTIME);
+ if (ret == UA_STATUSCODE_GOOD) {
+ UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "UA_PubSubComponent_updateMonitoringInterval(): DataSetReader '%.*s' - MessageReceiveTimeout: new MessageReceiveTimeout = '%f' "
+ "Timer Id = '%u'", (UA_Int32) reader->config.name.length, reader->config.name.data,
+ reader->config.messageReceiveTimeout, (UA_UInt32) reader->msgRcvTimeoutTimerId);
+ } else {
+ UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Error UA_PubSubComponent_updateMonitoringInterval(): DataSetReader '%.*s': update timer interval failed",
+ (UA_Int32) reader->config.name.length, reader->config.name.data);
+ }
+ break;
+ }
+ default:
+ UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER, "UA_PubSubComponent_createMonitoring(): DataSetReader '%.*s' "
+ "DataSetReader does not support timeout type '%i'", (UA_Int32) reader->config.name.length, reader->config.name.data,
+ eMonitoringType);
+ ret = UA_STATUSCODE_BADNOTSUPPORTED;
+ break;
+ }
+ break;
+ }
+ default:
+ UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Error UA_PubSubComponent_updateMonitoringInterval(): PubSub component type '%i' is not supported", eComponentType);
+ ret = UA_STATUSCODE_BADNOTSUPPORTED;
+ break;
+ }
+ return ret;
+}
+
+static UA_StatusCode
+UA_PubSubComponent_deleteMonitoring(UA_Server *server, UA_NodeId Id, UA_PubSubComponentEnumType eComponentType,
+ UA_PubSubMonitoringType eMonitoringType, void *data) {
+
+ if ((!server) || (!data)) {
+ UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER, "Error UA_PubSubComponent_deleteMonitoring(): "
+ "null pointer param");
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+ }
+ UA_StatusCode ret = UA_STATUSCODE_GOOD;
+ switch (eComponentType) {
+ case UA_PUBSUB_COMPONENT_DATASETREADER: {
+ UA_DataSetReader *reader = (UA_DataSetReader*) data;
+ switch (eMonitoringType) {
+ case UA_PUBSUB_MONITORING_MESSAGE_RECEIVE_TIMEOUT:
+ UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "UA_PubSubComponent_deleteMonitoring(): DataSetReader '%.*s' - MessageReceiveTimeout: Timer Id = '%u'",
+ (UA_Int32) reader->config.name.length, reader->config.name.data, (UA_UInt32) reader->msgRcvTimeoutTimerId);
+ break;
+ default:
+ UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER, "UA_PubSubComponent_deleteMonitoring(): DataSetReader '%.*s' "
+ "DataSetReader does not support timeout type '%i'", (UA_Int32) reader->config.name.length, reader->config.name.data,
+ eMonitoringType);
+ ret = UA_STATUSCODE_BADNOTSUPPORTED;
+ break;
+ }
+ break;
+ }
+ default:
+ UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Error UA_PubSubComponent_deleteMonitoring(): PubSub component type '%i' is not supported", eComponentType);
+ ret = UA_STATUSCODE_BADNOTSUPPORTED;
+ break;
+ }
+ return ret;
+}
+
+UA_StatusCode
+UA_PubSubManager_setDefaultMonitoringCallbacks(UA_PubSubMonitoringInterface *monitoringInterface) {
+ if (monitoringInterface == NULL) {
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+ }
+ monitoringInterface->createMonitoring = UA_PubSubComponent_createMonitoring;
+ monitoringInterface->startMonitoring = UA_PubSubComponent_startMonitoring;
+ monitoringInterface->stopMonitoring = UA_PubSubComponent_stopMonitoring;
+ monitoringInterface->updateMonitoringInterval = UA_PubSubComponent_updateMonitoringInterval;
+ monitoringInterface->deleteMonitoring = UA_PubSubComponent_deleteMonitoring;
+ return UA_STATUSCODE_GOOD;
+}
+
+#endif /* UA_ENABLE_PUBSUB_MONITORING */
#endif /* UA_ENABLE_PUBSUB */
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/src/pubsub/ua_pubsub_ns0.c" ***********************************/
+/**** amalgamated original file "/src/pubsub/ua_pubsub_ns0.c" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Copyright (c) 2017-2018 Fraunhofer IOSB (Author: Andreas Ebner)
- * Copyright (c) 2019 Kalycito Infotech Private Limited
+ * Copyright (c) 2019-2021 Kalycito Infotech Private Limited
+ * Copyright (c) 2020 Yannick Wallerer, Siemens AG
+ * Copyright (c) 2020 Thomas Fischer, Siemens AG
*/
+#ifdef UA_ENABLE_PUBSUB_FILE_CONFIG
+#endif
+
#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL /* conditional compilation */
-typedef struct{
+typedef struct {
UA_NodeId parentNodeId;
UA_UInt32 parentClassifier;
UA_UInt32 elementClassiefier;
} UA_NodePropertyContext;
-//Prototypes
-#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL_METHODS
-static UA_StatusCode addWriterGroupAction(UA_Server *server,
- const UA_NodeId *sessionId, void *sessionHandle,
- const UA_NodeId *methodId, void *methodContext,
- const UA_NodeId *objectId, void *objectContext,
- size_t inputSize, const UA_Variant *input,
- size_t outputSize, UA_Variant *output);
-static UA_StatusCode removeGroupAction(UA_Server *server,
- const UA_NodeId *sessionId, void *sessionHandle,
- const UA_NodeId *methodId, void *methodContext,
- const UA_NodeId *objectId, void *objectContext,
- size_t inputSize, const UA_Variant *input,
- size_t outputSize, UA_Variant *output);
-static UA_StatusCode addDataSetWriterAction(UA_Server *server,
- const UA_NodeId *sessionId, void *sessionHandle,
- const UA_NodeId *methodId, void *methodContext,
- const UA_NodeId *objectId, void *objectContext,
- size_t inputSize, const UA_Variant *input,
- size_t outputSize, UA_Variant *output);
-
-#endif
-
-static UA_StatusCode
-addPubSubObjectNode(UA_Server *server, char* name, UA_UInt32 objectid,
- UA_UInt32 parentid, UA_UInt32 referenceid, UA_UInt32 type_id) {
- UA_ObjectAttributes object_attr = UA_ObjectAttributes_default;
- object_attr.displayName = UA_LOCALIZEDTEXT("", name);
- return UA_Server_addObjectNode(server, UA_NODEID_NUMERIC(0, objectid),
- UA_NODEID_NUMERIC(0, parentid),
- UA_NODEID_NUMERIC(0, referenceid),
- UA_QUALIFIEDNAME(0, name),
- UA_NODEID_NUMERIC(0, type_id),
- object_attr, NULL, NULL);
-}
-
static UA_StatusCode
writePubSubNs0VariableArray(UA_Server *server, UA_UInt32 id, void *v,
size_t length, const UA_DataType *type) {
@@ -31302,16 +33178,16 @@ findSingleChildNode(UA_Server *server, UA_QualifiedName targetName,
bp.startingNode = startingNode;
bp.relativePath.elementsSize = 1;
bp.relativePath.elements = &rpe;
- UA_BrowsePathResult bpr =
- UA_Server_translateBrowsePathToNodeIds(server, &bp);
+ UA_BrowsePathResult bpr = UA_Server_translateBrowsePathToNodeIds(server, &bp);
if(bpr.statusCode != UA_STATUSCODE_GOOD ||
bpr.targetsSize < 1)
return UA_NODEID_NULL;
- if(UA_NodeId_copy(&bpr.targets[0].targetId.nodeId, &resultNodeId) != UA_STATUSCODE_GOOD){
- UA_BrowsePathResult_deleteMembers(&bpr);
+ UA_StatusCode res = UA_NodeId_copy(&bpr.targets[0].targetId.nodeId, &resultNodeId);
+ if(res != UA_STATUSCODE_GOOD){
+ UA_BrowsePathResult_clear(&bpr);
return UA_NODEID_NULL;
}
- UA_BrowsePathResult_deleteMembers(&bpr);
+ UA_BrowsePathResult_clear(&bpr);
return resultNodeId;
}
@@ -31344,6 +33220,22 @@ onRead(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext,
}
break;
}
+ case UA_NS0ID_DATASETREADERTYPE: {
+ UA_DataSetReader *dataSetReader = UA_ReaderGroup_findDSRbyId(server, *myNodeId);
+ if(!dataSetReader)
+ return;
+
+ switch(nodeContext->elementClassiefier) {
+ case UA_NS0ID_DATASETREADERTYPE_PUBLISHERID:
+ UA_Variant_setScalar(&value, dataSetReader->config.publisherId.data,
+ dataSetReader->config.publisherId.type);
+ break;
+ default:
+ UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Read error! Unknown property.");
+ }
+ break;
+ }
case UA_NS0ID_WRITERGROUPTYPE: {
UA_WriterGroup *writerGroup = UA_WriterGroup_findWGbyId(server, *myNodeId);
if(!writerGroup)
@@ -31359,6 +33251,22 @@ onRead(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext,
}
break;
}
+ case UA_NS0ID_DATASETWRITERTYPE: {
+ UA_DataSetWriter *dataSetWriter = UA_DataSetWriter_findDSWbyId(server, *myNodeId);
+ if(!dataSetWriter)
+ return;
+
+ switch(nodeContext->elementClassiefier) {
+ case UA_NS0ID_DATASETWRITERTYPE_DATASETWRITERID:
+ UA_Variant_setScalar(&value, &dataSetWriter->config.dataSetWriterId,
+ &UA_TYPES[UA_TYPES_UINT16]);
+ break;
+ default:
+ UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Read error! Unknown property.");
+ }
+ break;
+ }
case UA_NS0ID_PUBLISHEDDATAITEMSTYPE: {
UA_PublishedDataSet *publishedDataSet = UA_PublishedDataSet_findPDSbyId(server, *myNodeId);
if(!publishedDataSet)
@@ -31445,60 +33353,340 @@ addVariableValueSource(UA_Server *server, UA_ValueCallback valueCallback,
return UA_Server_setVariableNode_valueCallback(server, node, valueCallback);
}
+#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL_METHODS
+static UA_StatusCode
+addPubSubConnectionConfig(UA_Server *server, UA_PubSubConnectionDataType *pubsubConnectionDataType,
+ UA_NodeId *connectionId){
+ UA_StatusCode retVal = UA_STATUSCODE_GOOD;
+ UA_NetworkAddressUrlDataType networkAddressUrlDataType;
+ memset(&networkAddressUrlDataType, 0, sizeof(networkAddressUrlDataType));
+ UA_ExtensionObject eo = pubsubConnectionDataType->address;
+ if(eo.encoding == UA_EXTENSIONOBJECT_DECODED){
+ if(eo.content.decoded.type == &UA_TYPES[UA_TYPES_NETWORKADDRESSURLDATATYPE]){
+ if(UA_NetworkAddressUrlDataType_copy((UA_NetworkAddressUrlDataType *) eo.content.decoded.data,
+ &networkAddressUrlDataType) != UA_STATUSCODE_GOOD){
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ }
+ }
+ }
+
+ UA_PubSubConnectionConfig connectionConfig;
+ memset(&connectionConfig, 0, sizeof(UA_PubSubConnectionConfig));
+ connectionConfig.transportProfileUri = pubsubConnectionDataType->transportProfileUri;
+ connectionConfig.name = pubsubConnectionDataType->name;
+ //TODO set real connection state
+ connectionConfig.enabled = pubsubConnectionDataType->enabled;
+ //connectionConfig.enabled = pubSubConnectionDataType.enabled;
+ UA_Variant_setScalar(&connectionConfig.address, &networkAddressUrlDataType,
+ &UA_TYPES[UA_TYPES_NETWORKADDRESSURLDATATYPE]);
+ if(pubsubConnectionDataType->publisherId.type == &UA_TYPES[UA_TYPES_UINT32]){
+ connectionConfig.publisherId.numeric = * ((UA_UInt32 *) pubsubConnectionDataType->publisherId.data);
+ } else if(pubsubConnectionDataType->publisherId.type == &UA_TYPES[UA_TYPES_STRING]){
+ connectionConfig.publisherIdType = UA_PUBSUB_PUBLISHERID_STRING;
+ UA_String_copy((UA_String *) pubsubConnectionDataType->publisherId.data, &connectionConfig.publisherId.string);
+ } else {
+ UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER, "Unsupported PublisherId Type used.");
+ //TODO what's the best default behaviour here?
+ connectionConfig.publisherId.numeric = 0;
+ }
+
+ retVal |= UA_Server_addPubSubConnection(server, &connectionConfig, connectionId);
+ UA_NetworkAddressUrlDataType_clear(&networkAddressUrlDataType);
+ return retVal;
+}
+
+/**
+ * **WriterGroup handling**
+ *
+ * The WriterGroup (WG) is part of the connection and contains the primary
+ * configuration parameters for the message creation. */
+static UA_StatusCode
+addWriterGroupConfig(UA_Server *server, UA_NodeId connectionId,
+ UA_WriterGroupDataType *writerGroupDataType, UA_NodeId *writerGroupId){
+ /* Now we create a new WriterGroupConfig and add the group to the existing
+ * PubSubConnection. */
+ UA_WriterGroupConfig writerGroupConfig;
+ memset(&writerGroupConfig, 0, sizeof(UA_WriterGroupConfig));
+ writerGroupConfig.name = writerGroupDataType->name;
+ writerGroupConfig.publishingInterval = writerGroupDataType->publishingInterval;
+ writerGroupConfig.enabled = writerGroupDataType->enabled;
+ writerGroupConfig.writerGroupId = writerGroupDataType->writerGroupId;
+ //TODO remove hard coded UADP
+ writerGroupConfig.encodingMimeType = UA_PUBSUB_ENCODING_UADP;
+ writerGroupConfig.priority = writerGroupDataType->priority;
+
+ UA_UadpWriterGroupMessageDataType writerGroupMessage;
+ UA_ExtensionObject *eoWG = &writerGroupDataType->messageSettings;
+ if(eoWG->encoding == UA_EXTENSIONOBJECT_DECODED){
+ writerGroupConfig.messageSettings.encoding = UA_EXTENSIONOBJECT_DECODED;
+ if(eoWG->content.decoded.type == &UA_TYPES[UA_TYPES_UADPWRITERGROUPMESSAGEDATATYPE]){
+ if(UA_UadpWriterGroupMessageDataType_copy((UA_UadpWriterGroupMessageDataType *) eoWG->content.decoded.data,
+ &writerGroupMessage) != UA_STATUSCODE_GOOD){
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ }
+ writerGroupConfig.messageSettings.content.decoded.type = &UA_TYPES[UA_TYPES_UADPWRITERGROUPMESSAGEDATATYPE];
+ writerGroupConfig.messageSettings.content.decoded.data = &writerGroupMessage;
+ }
+ }
+
+ return UA_Server_addWriterGroup(server, connectionId, &writerGroupConfig, writerGroupId);
+}
+
+/**
+ * **DataSetWriter handling**
+ *
+ * A DataSetWriter (DSW) is the glue between the WG and the PDS. The DSW is
+ * linked to exactly one PDS and contains additional informations for the
+ * message generation. */
+static UA_StatusCode
+addDataSetWriterConfig(UA_Server *server, const UA_NodeId *writerGroupId,
+ UA_DataSetWriterDataType *dataSetWriterDataType,
+ UA_NodeId *dataSetWriterId) {
+ UA_NodeId publishedDataSetId = UA_NODEID_NULL;
+ UA_PublishedDataSet *tmpPDS;
+ TAILQ_FOREACH(tmpPDS, &server->pubSubManager.publishedDataSets, listEntry){
+ if(UA_String_equal(&dataSetWriterDataType->dataSetName, &tmpPDS->config.name)) {
+ publishedDataSetId = tmpPDS->identifier;
+ break;
+ }
+ }
+
+ if(UA_NodeId_isNull(&publishedDataSetId))
+ return UA_STATUSCODE_BADPARENTNODEIDINVALID;
+
+ /* We need now a DataSetWriter within the WriterGroup. This means we must
+ * create a new DataSetWriterConfig and add call the addWriterGroup function. */
+ UA_DataSetWriterConfig dataSetWriterConfig;
+ memset(&dataSetWriterConfig, 0, sizeof(UA_DataSetWriterConfig));
+ dataSetWriterConfig.name = dataSetWriterDataType->name;
+ dataSetWriterConfig.dataSetWriterId = dataSetWriterDataType->dataSetWriterId;
+ dataSetWriterConfig.keyFrameCount = dataSetWriterDataType->keyFrameCount;
+ dataSetWriterConfig.dataSetFieldContentMask = dataSetWriterDataType->dataSetFieldContentMask;
+ return UA_Server_addDataSetWriter(server, *writerGroupId, publishedDataSetId,
+ &dataSetWriterConfig, dataSetWriterId);
+}
+
+/**
+ * **ReaderGroup**
+ *
+ * ReaderGroup is used to group a list of DataSetReaders. All ReaderGroups are
+ * created within a PubSubConnection and automatically deleted if the connection
+ * is removed. All network message related filters are only available in the DataSetReader. */
+/* Add ReaderGroup to the created connection */
+static UA_StatusCode
+addReaderGroupConfig(UA_Server *server, UA_NodeId connectionId,
+ UA_ReaderGroupDataType *readerGroupDataType,
+ UA_NodeId *readerGroupId) {
+ UA_ReaderGroupConfig readerGroupConfig;
+ memset(&readerGroupConfig, 0, sizeof(UA_ReaderGroupConfig));
+ readerGroupConfig.name = readerGroupDataType->name;
+ return UA_Server_addReaderGroup(server, connectionId,
+ &readerGroupConfig, readerGroupId);
+}
+
+/**
+ * **SubscribedDataSet**
+ *
+ * Set SubscribedDataSet type to TargetVariables data type.
+ * Add subscribedvariables to the DataSetReader */
+static UA_StatusCode
+addSubscribedVariables(UA_Server *server, UA_NodeId dataSetReaderId,
+ UA_DataSetReaderDataType *dataSetReaderDataType,
+ UA_DataSetMetaDataType *pMetaData) {
+ UA_StatusCode retVal = UA_STATUSCODE_GOOD;
+ UA_TargetVariablesDataType targetVars;
+ UA_ExtensionObject *eoTargetVar = &dataSetReaderDataType->subscribedDataSet;
+ if(eoTargetVar->encoding == UA_EXTENSIONOBJECT_DECODED){
+ if(eoTargetVar->content.decoded.type == &UA_TYPES[UA_TYPES_TARGETVARIABLESDATATYPE]){
+ if(UA_TargetVariablesDataType_copy((UA_TargetVariablesDataType *) eoTargetVar->content.decoded.data,
+ &targetVars) != UA_STATUSCODE_GOOD){
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ }
+ }
+ UA_NodeId folderId;
+ UA_String folderName = pMetaData->name;
+ UA_ObjectAttributes oAttr = UA_ObjectAttributes_default;
+ UA_QualifiedName folderBrowseName;
+ if(folderName.length > 0) {
+ oAttr.displayName.locale = UA_STRING("");
+ oAttr.displayName.text = folderName;
+ folderBrowseName.namespaceIndex = 1;
+ folderBrowseName.name = folderName;
+ } else {
+ oAttr.displayName = UA_LOCALIZEDTEXT("", "Subscribed Variables");
+ folderBrowseName = UA_QUALIFIEDNAME(1, "Subscribed Variables");
+ }
+
+ UA_Server_addObjectNode(server, UA_NODEID_NULL,
+ UA_NODEID_NUMERIC (0, UA_NS0ID_OBJECTSFOLDER),
+ UA_NODEID_NUMERIC (0, UA_NS0ID_ORGANIZES),
+ folderBrowseName, UA_NODEID_NUMERIC (0,
+ UA_NS0ID_BASEOBJECTTYPE), oAttr, NULL, &folderId);
+ /**
+ * **TargetVariables**
+ *
+ * The SubscribedDataSet option TargetVariables defines a list of Variable mappings between
+ * received DataSet fields and target Variables in the Subscriber AddressSpace.
+ * The values subscribed from the Publisher are updated in the value field of these variables */
+ /* Create the TargetVariables with respect to DataSetMetaData fields */
+ UA_FieldTargetVariable *targetVarsData = (UA_FieldTargetVariable *)
+ UA_calloc(targetVars.targetVariablesSize, sizeof(UA_FieldTargetVariable));
+ for(size_t i = 0; i < targetVars.targetVariablesSize; i++) {
+ /* Variable to subscribe data */
+ UA_VariableAttributes vAttr = UA_VariableAttributes_default;
+ UA_LocalizedText_copy(&pMetaData->fields[i].description,
+ &vAttr.description);
+ vAttr.displayName.locale = UA_STRING("");
+ vAttr.displayName.text = pMetaData->fields[i].name;
+ vAttr.dataType = pMetaData->fields[i].dataType;
+
+ UA_NodeId newNode;
+ retVal |= UA_Server_addVariableNode(server, targetVars.targetVariables[i].targetNodeId,
+ folderId,
+ UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
+ UA_QUALIFIEDNAME(1, (char *)pMetaData->fields[i].name.data),
+ UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE),
+ vAttr, NULL, &newNode);
+
+ /* For creating Targetvariables */
+ UA_FieldTargetDataType_init(&targetVarsData[i].targetVariable);
+ targetVarsData[i].targetVariable.attributeId = targetVars.targetVariables[i].attributeId;
+ targetVarsData[i].targetVariable.targetNodeId = newNode;
+ }
+ retVal = UA_Server_DataSetReader_createTargetVariables(server, dataSetReaderId,
+ targetVars.targetVariablesSize, targetVarsData);
+ for(size_t j = 0; j < targetVars.targetVariablesSize; j++)
+ UA_FieldTargetDataType_clear(&targetVarsData[j].targetVariable);
+ UA_free(targetVarsData);
+ }
+
+ return retVal;
+}
+
+/**
+ * **DataSetReader**
+ *
+ * DataSetReader can receive NetworkMessages with the DataSetMessage
+ * of interest sent by the Publisher. DataSetReader provides
+ * the configuration necessary to receive and process DataSetMessages
+ * on the Subscriber side. DataSetReader must be linked with a
+ * SubscribedDataSet and be contained within a ReaderGroup. */
+/* Add DataSetReader to the ReaderGroup */
+static UA_StatusCode
+addDataSetReaderConfig(UA_Server *server, UA_NodeId readerGroupId,
+ UA_DataSetReaderDataType *dataSetReaderDataType,
+ UA_NodeId *dataSetReaderId) {
+ UA_StatusCode retVal = UA_STATUSCODE_GOOD;
+ UA_DataSetReaderConfig readerConfig;
+ memset (&readerConfig, 0, sizeof(UA_DataSetReaderConfig));
+ readerConfig.name = dataSetReaderDataType->name;
+ /* Parameters to filter which DataSetMessage has to be processed
+ * by the DataSetReader */
+ if(dataSetReaderDataType->publisherId.type == &UA_TYPES[UA_TYPES_STRING]){
+ UA_String publisherIdentifier;
+ readerConfig.publisherId.type = &UA_TYPES[UA_TYPES_STRING];
+ UA_String_copy((UA_String *) dataSetReaderDataType->publisherId.data, &publisherIdentifier);
+ readerConfig.publisherId.data = &publisherIdentifier;
+ } else {
+ UA_UInt16 publisherIdentifier = *(UA_UInt16*)dataSetReaderDataType->publisherId.data;
+ readerConfig.publisherId.type = &UA_TYPES[UA_TYPES_UINT16];
+ readerConfig.publisherId.data = &publisherIdentifier;
+ }
+
+ readerConfig.writerGroupId = dataSetReaderDataType->writerGroupId;
+ readerConfig.dataSetWriterId = dataSetReaderDataType->dataSetWriterId;
+
+ /* Setting up Meta data configuration in DataSetReader */
+ UA_DataSetMetaDataType *pMetaData;
+ pMetaData = &readerConfig.dataSetMetaData;
+ UA_DataSetMetaDataType_init (pMetaData);
+ pMetaData->name = dataSetReaderDataType->dataSetMetaData.name;
+ pMetaData->fieldsSize = dataSetReaderDataType->dataSetMetaData.fieldsSize;
+ pMetaData->fields = (UA_FieldMetaData*)UA_Array_new (pMetaData->fieldsSize,
+ &UA_TYPES[UA_TYPES_FIELDMETADATA]);
+ for(size_t i = 0; i < pMetaData->fieldsSize; i++){
+ UA_FieldMetaData_init (&pMetaData->fields[i]);
+ UA_NodeId_copy (&dataSetReaderDataType->dataSetMetaData.fields[i].dataType,
+ &pMetaData->fields[i].dataType);
+ pMetaData->fields[i].builtInType = dataSetReaderDataType->dataSetMetaData.fields[i].builtInType;
+ pMetaData->fields[i].name = dataSetReaderDataType->dataSetMetaData.fields[i].name;
+ pMetaData->fields[i].valueRank = dataSetReaderDataType->dataSetMetaData.fields[i].valueRank;
+ }
+
+ retVal |= UA_Server_addDataSetReader(server, readerGroupId, &readerConfig,
+ dataSetReaderId);
+ if(retVal != UA_STATUSCODE_GOOD) {
+ UA_free(pMetaData->fields);
+ return retVal;
+ }
+
+ retVal |= addSubscribedVariables(server, *dataSetReaderId, dataSetReaderDataType, pMetaData);
+ UA_free(pMetaData->fields);
+ return retVal;
+}
+#endif
+
/*************************************************/
/* PubSubConnection */
/*************************************************/
UA_StatusCode
-addPubSubConnectionRepresentation(UA_Server *server, UA_PubSubConnection *connection){
+addPubSubConnectionRepresentation(UA_Server *server, UA_PubSubConnection *connection) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
if(connection->config->name.length > 512)
return UA_STATUSCODE_BADOUTOFMEMORY;
- UA_STACKARRAY(char, connectionName, sizeof(char) * connection->config->name.length +1);
+ char connectionName[513];
memcpy(connectionName, connection->config->name.data, connection->config->name.length);
connectionName[connection->config->name.length] = '\0';
- //This code block must use a lock
- UA_NODESTORE_REMOVE(server, &connection->identifier);
- UA_NodeId pubSubConnectionNodeId;
+
UA_ObjectAttributes attr = UA_ObjectAttributes_default;
- attr.displayName = UA_LOCALIZEDTEXT("de-DE", connectionName);
+ attr.displayName = UA_LOCALIZEDTEXT("", connectionName);
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECT,
- UA_NODEID_NUMERIC(0, connection->identifier.identifier.numeric),
+ UA_NODEID_NUMERIC(1, 0), /* Generate a new id */
UA_NODEID_NUMERIC(0, UA_NS0ID_PUBLISHSUBSCRIBE),
UA_NODEID_NUMERIC(0, UA_NS0ID_HASPUBSUBCONNECTION),
UA_QUALIFIEDNAME(0, connectionName),
UA_NODEID_NUMERIC(0, UA_NS0ID_PUBSUBCONNECTIONTYPE),
- (const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],
- NULL, &pubSubConnectionNodeId);
- addPubSubObjectNode(server, "Address", connection->identifier.identifier.numeric+1,
- pubSubConnectionNodeId.identifier.numeric, UA_NS0ID_HASCOMPONENT,
- UA_NS0ID_NETWORKADDRESSURLTYPE);
- UA_Server_addNode_finish(server, pubSubConnectionNodeId);
- //End lock zone
-
- UA_NodeId addressNode, urlNode, interfaceNode, publisherIdNode, connectionPropertieNode, transportProfileUri;
+ (const UA_NodeAttributes*)&attr,
+ &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],
+ NULL, &connection->identifier);
+
+ attr.displayName = UA_LOCALIZEDTEXT("", "Address");
+ retVal |= UA_Server_addObjectNode(server, UA_NODEID_NUMERIC(1, 0),
+ connection->identifier,
+ UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
+ UA_QUALIFIEDNAME(0, "Address"),
+ UA_NODEID_NUMERIC(0, UA_NS0ID_NETWORKADDRESSURLTYPE),
+ attr, NULL, NULL);
+
+ UA_Server_addNode_finish(server, connection->identifier);
+
+ UA_NodeId addressNode, urlNode, interfaceNode, publisherIdNode,
+ connectionPropertieNode, transportProfileUri;
addressNode = findSingleChildNode(server, UA_QUALIFIEDNAME(0, "Address"),
UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
- UA_NODEID_NUMERIC(0, connection->identifier.identifier.numeric));
+ connection->identifier);
urlNode = findSingleChildNode(server, UA_QUALIFIEDNAME(0, "Url"),
- UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), addressNode);
+ UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
+ addressNode);
interfaceNode = findSingleChildNode(server, UA_QUALIFIEDNAME(0, "NetworkInterface"),
- UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), addressNode);
+ UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
+ addressNode);
publisherIdNode = findSingleChildNode(server, UA_QUALIFIEDNAME(0, "PublisherId"),
UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY),
- UA_NODEID_NUMERIC(0, connection->identifier.identifier.numeric));
- connectionPropertieNode = findSingleChildNode(server, UA_QUALIFIEDNAME(0, "ConnectionProperties"),
- UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY),
- UA_NODEID_NUMERIC(0, connection->identifier.identifier.numeric));
- transportProfileUri = findSingleChildNode(server, UA_QUALIFIEDNAME(0, "TransportProfileUri"),
- UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
- UA_NODEID_NUMERIC(0, connection->identifier.identifier.numeric));
-
- if(UA_NodeId_equal(&addressNode, &UA_NODEID_NULL) ||
- UA_NodeId_equal(&urlNode, &UA_NODEID_NULL) ||
- UA_NodeId_equal(&interfaceNode, &UA_NODEID_NULL) ||
- UA_NodeId_equal(&publisherIdNode, &UA_NODEID_NULL) ||
- UA_NodeId_equal(&connectionPropertieNode, &UA_NODEID_NULL) ||
- UA_NodeId_equal(&transportProfileUri, &UA_NODEID_NULL)) {
+ connection->identifier);
+ connectionPropertieNode = findSingleChildNode(server,
+ UA_QUALIFIEDNAME(0, "ConnectionProperties"),
+ UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY),
+ connection->identifier);
+ transportProfileUri = findSingleChildNode(server,
+ UA_QUALIFIEDNAME(0, "TransportProfileUri"),
+ UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
+ connection->identifier);
+
+ if(UA_NodeId_isNull(&addressNode) || UA_NodeId_isNull(&urlNode) ||
+ UA_NodeId_isNull(&interfaceNode) || UA_NodeId_isNull(&publisherIdNode) ||
+ UA_NodeId_isNull(&connectionPropertieNode) ||
+ UA_NodeId_isNull(&transportProfileUri)) {
return UA_STATUSCODE_BADNOTFOUND;
}
@@ -31507,35 +33695,45 @@ addPubSubConnectionRepresentation(UA_Server *server, UA_PubSubConnection *connec
connection->config->connectionPropertiesSize,
&UA_TYPES[UA_TYPES_KEYVALUEPAIR]);
- UA_NetworkAddressUrlDataType *networkAddressUrlDataType = ((UA_NetworkAddressUrlDataType *) connection->config->address.data);
+ UA_NetworkAddressUrlDataType *networkAddressUrlDataType =
+ ((UA_NetworkAddressUrlDataType*)connection->config->address.data);
UA_Variant value;
UA_Variant_init(&value);
- UA_Variant_setScalar(&value, &networkAddressUrlDataType->url, &UA_TYPES[UA_TYPES_STRING]);
+ UA_Variant_setScalar(&value, &networkAddressUrlDataType->url,
+ &UA_TYPES[UA_TYPES_STRING]);
UA_Server_writeValue(server, urlNode, value);
- UA_Variant_setScalar(&value, &networkAddressUrlDataType->networkInterface, &UA_TYPES[UA_TYPES_STRING]);
+ UA_Variant_setScalar(&value, &networkAddressUrlDataType->networkInterface,
+ &UA_TYPES[UA_TYPES_STRING]);
UA_Server_writeValue(server, interfaceNode, value);
- UA_Variant_setScalar(&value, &connection->config->transportProfileUri, &UA_TYPES[UA_TYPES_STRING]);
+ UA_Variant_setScalar(&value, &connection->config->transportProfileUri,
+ &UA_TYPES[UA_TYPES_STRING]);
UA_Server_writeValue(server, transportProfileUri, value);
- UA_NodePropertyContext *connectionPublisherIdContext = (UA_NodePropertyContext *) UA_malloc(sizeof(UA_NodePropertyContext));
+ UA_NodePropertyContext *connectionPublisherIdContext = (UA_NodePropertyContext *)
+ UA_malloc(sizeof(UA_NodePropertyContext));
connectionPublisherIdContext->parentNodeId = connection->identifier;
connectionPublisherIdContext->parentClassifier = UA_NS0ID_PUBSUBCONNECTIONTYPE;
- connectionPublisherIdContext->elementClassiefier = UA_NS0ID_PUBSUBCONNECTIONTYPE_PUBLISHERID;
+ connectionPublisherIdContext->elementClassiefier =
+ UA_NS0ID_PUBSUBCONNECTIONTYPE_PUBLISHERID;
UA_ValueCallback valueCallback;
valueCallback.onRead = onRead;
valueCallback.onWrite = NULL;
- retVal |= addVariableValueSource(server, valueCallback, publisherIdNode, connectionPublisherIdContext);
+ retVal |= addVariableValueSource(server, valueCallback, publisherIdNode,
+ connectionPublisherIdContext);
#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL_METHODS
retVal |= UA_Server_addReference(server, connection->identifier,
UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
- UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_PUBSUBCONNECTIONTYPE_ADDWRITERGROUP), true);
+ UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_PUBSUBCONNECTIONTYPE_ADDWRITERGROUP),
+ true);
retVal |= UA_Server_addReference(server, connection->identifier,
UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
- UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_PUBSUBCONNECTIONTYPE_ADDREADERGROUP), true);
+ UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_PUBSUBCONNECTIONTYPE_ADDREADERGROUP),
+ true);
retVal |= UA_Server_addReference(server, connection->identifier,
UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
- UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_PUBSUBCONNECTIONTYPE_REMOVEGROUP), true);
+ UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_PUBSUBCONNECTIONTYPE_REMOVEGROUP),
+ true);
#endif
return retVal;
}
@@ -31550,51 +33748,67 @@ addPubSubConnectionAction(UA_Server *server,
size_t outputSize, UA_Variant *output){
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_PubSubConnectionDataType pubSubConnectionDataType = *((UA_PubSubConnectionDataType *) input[0].data);
- UA_NetworkAddressUrlDataType networkAddressUrlDataType;
- memset(&networkAddressUrlDataType, 0, sizeof(networkAddressUrlDataType));
- UA_ExtensionObject eo = pubSubConnectionDataType.address;
- if(eo.encoding == UA_EXTENSIONOBJECT_DECODED){
- if(eo.content.decoded.type == &UA_TYPES[UA_TYPES_NETWORKADDRESSURLDATATYPE]){
- if(UA_NetworkAddressUrlDataType_copy((UA_NetworkAddressUrlDataType *) eo.content.decoded.data,
- &networkAddressUrlDataType) != UA_STATUSCODE_GOOD){
- return UA_STATUSCODE_BADOUTOFMEMORY;
- }
- }
- }
- UA_PubSubConnectionConfig connectionConfig;
- memset(&connectionConfig, 0, sizeof(UA_PubSubConnectionConfig));
- connectionConfig.transportProfileUri = pubSubConnectionDataType.transportProfileUri;
- connectionConfig.name = pubSubConnectionDataType.name;
- //TODO set real connection state
- connectionConfig.enabled = pubSubConnectionDataType.enabled;
- //connectionConfig.enabled = pubSubConnectionDataType.enabled;
- UA_Variant_setScalar(&connectionConfig.address, &networkAddressUrlDataType,
- &UA_TYPES[UA_TYPES_NETWORKADDRESSURLDATATYPE]);
- if(pubSubConnectionDataType.publisherId.type == &UA_TYPES[UA_TYPES_UINT32]){
- connectionConfig.publisherId.numeric = * ((UA_UInt32 *) pubSubConnectionDataType.publisherId.data);
- } else if(pubSubConnectionDataType.publisherId.type == &UA_TYPES[UA_TYPES_STRING]){
- connectionConfig.publisherIdType = UA_PUBSUB_PUBLISHERID_STRING;
- UA_String_copy((UA_String *) pubSubConnectionDataType.publisherId.data, &connectionConfig.publisherId.string);
- } else {
- UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER, "Unsupported PublisherId Type used.");
- //TODO what's the best default behaviour here?
- connectionConfig.publisherId.numeric = 0;
- }
+
//call API function and create the connection
UA_NodeId connectionId;
-
- retVal |= UA_Server_addPubSubConnection(server, &connectionConfig, &connectionId);
-
- if(retVal != UA_STATUSCODE_GOOD){
+ retVal |= addPubSubConnectionConfig(server, &pubSubConnectionDataType, &connectionId);
+ if(retVal != UA_STATUSCODE_GOOD) {
+ UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER, "addPubSubConnection failed");
return retVal;
}
+
for(size_t i = 0; i < pubSubConnectionDataType.writerGroupsSize; i++){
- //UA_PubSubConnection_addWriterGroup(server, UA_NODEID_NULL, NULL, NULL);
+ UA_NodeId writerGroupId;
+ UA_WriterGroupDataType *writerGroupDataType = &pubSubConnectionDataType.writerGroups[i];
+ retVal |= addWriterGroupConfig(server, connectionId, writerGroupDataType, &writerGroupId);
+ if(retVal != UA_STATUSCODE_GOOD) {
+ UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER, "addWriterGroup failed");
+ return retVal;
+ }
+
+ for (size_t j = 0; j < pubSubConnectionDataType.writerGroups[i].dataSetWritersSize; j++){
+ UA_DataSetWriterDataType *dataSetWriterDataType = &writerGroupDataType->dataSetWriters[j];
+ retVal |= addDataSetWriterConfig(server, &writerGroupId, dataSetWriterDataType, NULL);
+ if(retVal != UA_STATUSCODE_GOOD) {
+ UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER, "addDataSetWriter failed");
+ return retVal;
+ }
+ }
+
+ //TODO: Need to handle the UA_Server_setWriterGroupOperational based on the status variable in information model
+ if(pubSubConnectionDataType.enabled) {
+ UA_Server_freezeWriterGroupConfiguration(server, writerGroupId);
+ UA_Server_setWriterGroupOperational(server, writerGroupId);
+ } else
+ UA_Server_setWriterGroupDisabled(server, writerGroupId);
}
+
for(size_t i = 0; i < pubSubConnectionDataType.readerGroupsSize; i++){
- //UA_Server_addReaderGroup(server, NULL, NULL, NULL);
+ UA_NodeId readerGroupId;
+ UA_ReaderGroupDataType *readerGroupDataType = &pubSubConnectionDataType.readerGroups[i];
+ retVal |= addReaderGroupConfig(server, connectionId, readerGroupDataType, &readerGroupId);
+ if(retVal != UA_STATUSCODE_GOOD) {
+ UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER, "addReaderGroup failed");
+ return retVal;
+ }
+
+ for(size_t j = 0; j < pubSubConnectionDataType.readerGroups[i].dataSetReadersSize; j++){
+ UA_NodeId dataSetReaderId;
+ UA_DataSetReaderDataType *dataSetReaderDataType = &readerGroupDataType->dataSetReaders[j];
+ retVal |= addDataSetReaderConfig(server, readerGroupId, dataSetReaderDataType, &dataSetReaderId);
+ if(retVal != UA_STATUSCODE_GOOD) {
+ UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER, "addDataSetReader failed");
+ return retVal;
+ }
+ }
+ //TODO: Need to handle the UA_Server_setReaderGroupOperational based on the status variable in information model
+ if(pubSubConnectionDataType.enabled) {
+ UA_Server_freezeReaderGroupConfiguration(server, readerGroupId);
+ UA_Server_setReaderGroupOperational(server, readerGroupId);
+ }
+ else
+ UA_Server_setReaderGroupDisabled(server, readerGroupId);
}
- UA_NetworkAddressUrlDataType_deleteMembers(&networkAddressUrlDataType);
//set ouput value
UA_Variant_setScalarCopy(output, &connectionId, &UA_TYPES[UA_TYPES_NODEID]);
return UA_STATUSCODE_GOOD;
@@ -31602,21 +33816,9 @@ addPubSubConnectionAction(UA_Server *server,
#endif
UA_StatusCode
-removePubSubConnectionRepresentation(UA_Server *server, UA_PubSubConnection *connection){
- UA_StatusCode retVal = UA_STATUSCODE_GOOD;
-#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL_METHODS
- retVal |= UA_Server_deleteReference(server, connection->identifier, UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), true,
- UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_PUBSUBCONNECTIONTYPE_ADDWRITERGROUP),
- false);
- retVal |= UA_Server_deleteReference(server, connection->identifier, UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), true,
- UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_PUBSUBCONNECTIONTYPE_ADDREADERGROUP),
- false);
- retVal |= UA_Server_deleteReference(server, connection->identifier, UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), true,
- UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_PUBSUBCONNECTIONTYPE_REMOVEGROUP),
- false);
-#endif
- retVal |= UA_Server_deleteNode(server, connection->identifier, true);
- return retVal;
+removePubSubConnectionRepresentation(UA_Server *server,
+ UA_PubSubConnection *connection) {
+ return UA_Server_deleteNode(server, connection->identifier, true);
}
#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL_METHODS
@@ -31641,8 +33843,64 @@ removeConnectionAction(UA_Server *server,
/**********************************************/
UA_StatusCode
addDataSetReaderRepresentation(UA_Server *server, UA_DataSetReader *dataSetReader){
- //TODO implement reader part
- return UA_STATUSCODE_BADNOTIMPLEMENTED;
+ if(dataSetReader->config.name.length > 512)
+ return UA_STATUSCODE_BADCONFIGURATIONERROR;
+
+ char dsrName[513];
+ memcpy(dsrName, dataSetReader->config.name.data, dataSetReader->config.name.length);
+ dsrName[dataSetReader->config.name.length] = '\0';
+
+ UA_StatusCode retVal = UA_STATUSCODE_GOOD;
+ UA_NodeId publisherIdNode, writerGroupIdNode, dataSetwriterIdNode;
+
+ UA_ObjectAttributes object_attr = UA_ObjectAttributes_default;
+ object_attr.displayName = UA_LOCALIZEDTEXT("", dsrName);
+ retVal = UA_Server_addObjectNode(server, UA_NODEID_NUMERIC(1, 0), /* create an id */
+ dataSetReader->linkedReaderGroup,
+ UA_NODEID_NUMERIC(0, UA_NS0ID_HASDATASETREADER),
+ UA_QUALIFIEDNAME(0, dsrName),
+ UA_NODEID_NUMERIC(0, UA_NS0ID_DATASETREADERTYPE),
+ object_attr, NULL, &dataSetReader->identifier);
+
+ /* Add childNodes such as PublisherId, WriterGroupId and DataSetWriterId in
+ * DataSetReader object */
+ publisherIdNode = findSingleChildNode(server, UA_QUALIFIEDNAME(0, "PublisherId"),
+ UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY),
+ dataSetReader->identifier);
+ writerGroupIdNode = findSingleChildNode(server, UA_QUALIFIEDNAME(0, "WriterGroupId"),
+ UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY),
+ dataSetReader->identifier);
+ dataSetwriterIdNode = findSingleChildNode(server, UA_QUALIFIEDNAME(0, "DataSetWriterId"),
+ UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY),
+ dataSetReader->identifier);
+
+ if(UA_NodeId_isNull(&publisherIdNode) ||
+ UA_NodeId_isNull(&writerGroupIdNode) ||
+ UA_NodeId_isNull(&dataSetwriterIdNode)) {
+ return UA_STATUSCODE_BADNOTFOUND;
+ }
+
+ UA_NodePropertyContext *dataSetReaderPublisherIdContext =
+ (UA_NodePropertyContext *) UA_malloc(sizeof(UA_NodePropertyContext));
+ dataSetReaderPublisherIdContext->parentNodeId = dataSetReader->identifier;
+ dataSetReaderPublisherIdContext->parentClassifier = UA_NS0ID_DATASETREADERTYPE;
+ dataSetReaderPublisherIdContext->elementClassiefier = UA_NS0ID_DATASETREADERTYPE_PUBLISHERID;
+ UA_ValueCallback valueCallback;
+ valueCallback.onRead = onRead;
+ valueCallback.onWrite = NULL;
+ retVal |= addVariableValueSource(server, valueCallback, publisherIdNode,
+ dataSetReaderPublisherIdContext);
+
+ /* Update childNode with values from Publisher */
+ UA_Variant value;
+ UA_Variant_init(&value);
+ UA_Variant_setScalar(&value, &dataSetReader->config.writerGroupId,
+ &UA_TYPES[UA_TYPES_UINT16]);
+ UA_Server_writeValue(server, writerGroupIdNode, value);
+ UA_Variant_setScalar(&value, &dataSetReader->config.dataSetWriterId,
+ &UA_TYPES[UA_TYPES_UINT16]);
+ UA_Server_writeValue(server, dataSetwriterIdNode, value);
+ return retVal;
}
#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL_METHODS
@@ -31653,16 +33911,31 @@ addDataSetReaderAction(UA_Server *server,
const UA_NodeId *objectId, void *objectContext,
size_t inputSize, const UA_Variant *input,
size_t outputSize, UA_Variant *output){
- UA_StatusCode retVal = UA_STATUSCODE_BADNOTIMPLEMENTED;
- //TODO implement reader part
+ UA_StatusCode retVal = UA_STATUSCODE_GOOD;
+ UA_ReaderGroup *rg = UA_ReaderGroup_findRGbyId(server, *objectId);
+ if(rg->configurationFrozen) {
+ UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "addDataSetReader cannot be done because ReaderGroup config frozen");
+ return UA_STATUSCODE_BAD;
+ }
+
+ UA_NodeId dataSetReaderId;
+ UA_DataSetReaderDataType *dataSetReaderDataType = (UA_DataSetReaderDataType *) input[0].data;
+ retVal |= addDataSetReaderConfig(server, *objectId, dataSetReaderDataType, &dataSetReaderId);
+ if(retVal != UA_STATUSCODE_GOOD) {
+ UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER, "addDataSetReader failed");
+ return retVal;
+ }
+
+ UA_Variant_setScalarCopy(output, &dataSetReaderId, &UA_TYPES[UA_TYPES_NODEID]);
return retVal;
}
#endif
UA_StatusCode
-removeDataSetReaderRepresentation(UA_Server *server, UA_DataSetReader* dataSetReader){
- //TODO implement reader part
- return UA_STATUSCODE_BADNOTIMPLEMENTED;
+removeDataSetReaderRepresentation(UA_Server *server,
+ UA_DataSetReader* dataSetReader) {
+ return UA_Server_deleteNode(server, dataSetReader->identifier, true);
}
#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL_METHODS
@@ -31673,9 +33946,8 @@ removeDataSetReaderAction(UA_Server *server,
const UA_NodeId *objectId, void *objectContext,
size_t inputSize, const UA_Variant *input,
size_t outputSize, UA_Variant *output){
- UA_StatusCode retVal = UA_STATUSCODE_BADNOTIMPLEMENTED;
- //TODO implement reader part
- return retVal;
+ UA_NodeId nodeToRemove = *((UA_NodeId *)input[0].data);
+ return UA_Server_removeDataSetReader(server, nodeToRemove);
}
#endif
@@ -31695,10 +33967,12 @@ addDataSetFolderAction(UA_Server *server,
UA_String newFolderName = *((UA_String *) input[0].data);
UA_NodeId generatedId;
UA_ObjectAttributes objectAttributes = UA_ObjectAttributes_default;
- UA_LocalizedText name = {UA_STRING("en-US"), newFolderName};
+ UA_LocalizedText name = {UA_STRING(""), newFolderName};
objectAttributes.displayName = name;
- retVal |= UA_Server_addObjectNode(server, UA_NODEID_NULL, *objectId, UA_NODEID_NUMERIC(0,UA_NS0ID_ORGANIZES),
- UA_QUALIFIEDNAME(0, "DataSetFolder"), UA_NODEID_NUMERIC(0, UA_NS0ID_DATASETFOLDERTYPE),
+ retVal |= UA_Server_addObjectNode(server, UA_NODEID_NULL, *objectId,
+ UA_NODEID_NUMERIC(0,UA_NS0ID_ORGANIZES),
+ UA_QUALIFIEDNAME(0, "DataSetFolder"),
+ UA_NODEID_NUMERIC(0, UA_NS0ID_DATASETFOLDERTYPE),
objectAttributes, NULL, &generatedId);
UA_Variant_setScalarCopy(output, &generatedId, &UA_TYPES[UA_TYPES_NODEID]);
#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL_METHODS
@@ -31726,55 +34000,44 @@ removeDataSetFolderAction(UA_Server *server,
const UA_NodeId *methodId, void *methodContext,
const UA_NodeId *objectId, void *objectContext,
size_t inputSize, const UA_Variant *input,
- size_t outputSize, UA_Variant *output){
- UA_StatusCode retVal = UA_STATUSCODE_GOOD;
+ size_t outputSize, UA_Variant *output) {
UA_NodeId nodeToRemove = *((UA_NodeId *) input[0].data);
-#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL_METHODS
- retVal |= UA_Server_deleteReference(server, nodeToRemove, UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), true,
- UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_DATASETFOLDERTYPE_ADDPUBLISHEDDATAITEMS),
- false);
- retVal |= UA_Server_deleteReference(server, nodeToRemove, UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), true,
- UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_DATASETFOLDERTYPE_REMOVEPUBLISHEDDATASET),
- false);
- retVal |= UA_Server_deleteReference(server, nodeToRemove, UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), true,
- UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_DATASETFOLDERTYPE_ADDDATASETFOLDER),
- false);
- retVal |= UA_Server_deleteReference(server, nodeToRemove, UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), true,
- UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_DATASETFOLDERTYPE_REMOVEDATASETFOLDER),
- false);
-#endif
- retVal |= UA_Server_deleteNode(server, nodeToRemove, false);
- return retVal;
+ return UA_Server_deleteNode(server, nodeToRemove, true);
}
#endif
UA_StatusCode
-addPublishedDataItemsRepresentation(UA_Server *server, UA_PublishedDataSet *publishedDataSet) {
+addPublishedDataItemsRepresentation(UA_Server *server,
+ UA_PublishedDataSet *publishedDataSet) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
if(publishedDataSet->config.name.length > 512)
return UA_STATUSCODE_BADOUTOFMEMORY;
- UA_STACKARRAY(char, pdsName, sizeof(char) * publishedDataSet->config.name.length +1);
+ char pdsName[513];
memcpy(pdsName, publishedDataSet->config.name.data, publishedDataSet->config.name.length);
pdsName[publishedDataSet->config.name.length] = '\0';
- //This code block must use a lock
- UA_NODESTORE_REMOVE(server, &publishedDataSet->identifier);
- retVal |= addPubSubObjectNode(server, pdsName, publishedDataSet->identifier.identifier.numeric,
- UA_NS0ID_PUBLISHSUBSCRIBE_PUBLISHEDDATASETS,
- UA_NS0ID_HASPROPERTY, UA_NS0ID_PUBLISHEDDATAITEMSTYPE);
- //End lock zone
+
+ UA_ObjectAttributes object_attr = UA_ObjectAttributes_default;
+ object_attr.displayName = UA_LOCALIZEDTEXT("", pdsName);
+ retVal = UA_Server_addObjectNode(server, UA_NODEID_NUMERIC(1, 0), /* Create a new id */
+ UA_NODEID_NUMERIC(0, UA_NS0ID_PUBLISHSUBSCRIBE_PUBLISHEDDATASETS),
+ UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
+ UA_QUALIFIEDNAME(0, pdsName),
+ UA_NODEID_NUMERIC(0, UA_NS0ID_PUBLISHEDDATAITEMSTYPE),
+ object_attr, NULL, &publishedDataSet->identifier);
+ UA_CHECK_STATUS(retVal, return retVal);
UA_ValueCallback valueCallback;
valueCallback.onRead = onRead;
valueCallback.onWrite = NULL;
-
+ //ToDo: Need to move the browse name from namespaceindex 0 to 1
UA_NodeId configurationVersionNode =
findSingleChildNode(server, UA_QUALIFIEDNAME(0, "ConfigurationVersion"),
UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY),
- UA_NODEID_NUMERIC(0, publishedDataSet->identifier.identifier.numeric));
- if(UA_NodeId_equal(&configurationVersionNode, &UA_NODEID_NULL))
+ publishedDataSet->identifier);
+ if(UA_NodeId_isNull(&configurationVersionNode))
return UA_STATUSCODE_BADNOTFOUND;
- UA_NodePropertyContext * configurationVersionContext = (UA_NodePropertyContext *)
+ UA_NodePropertyContext *configurationVersionContext = (UA_NodePropertyContext *)
UA_malloc(sizeof(UA_NodePropertyContext));
configurationVersionContext->parentNodeId = publishedDataSet->identifier;
configurationVersionContext->parentClassifier = UA_NS0ID_PUBLISHEDDATAITEMSTYPE;
@@ -31786,8 +34049,8 @@ addPublishedDataItemsRepresentation(UA_Server *server, UA_PublishedDataSet *publ
UA_NodeId publishedDataNode =
findSingleChildNode(server, UA_QUALIFIEDNAME(0, "PublishedData"),
UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY),
- UA_NODEID_NUMERIC(0, publishedDataSet->identifier.identifier.numeric));
- if(UA_NodeId_equal(&publishedDataNode, &UA_NODEID_NULL))
+ publishedDataSet->identifier);
+ if(UA_NodeId_isNull(&publishedDataNode))
return UA_STATUSCODE_BADNOTFOUND;
UA_NodePropertyContext * publishingIntervalContext = (UA_NodePropertyContext *)
@@ -31801,8 +34064,8 @@ addPublishedDataItemsRepresentation(UA_Server *server, UA_PublishedDataSet *publ
UA_NodeId dataSetMetaDataNode =
findSingleChildNode(server, UA_QUALIFIEDNAME(0, "DataSetMetaData"),
UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY),
- UA_NODEID_NUMERIC(0, publishedDataSet->identifier.identifier.numeric));
- if(UA_NodeId_equal(&dataSetMetaDataNode, &UA_NODEID_NULL))
+ publishedDataSet->identifier);
+ if(UA_NodeId_isNull(&dataSetMetaDataNode))
return UA_STATUSCODE_BADNOTFOUND;
UA_NodePropertyContext *metaDataContext = (UA_NodePropertyContext *)
@@ -31810,7 +34073,8 @@ addPublishedDataItemsRepresentation(UA_Server *server, UA_PublishedDataSet *publ
metaDataContext->parentNodeId = publishedDataSet->identifier;
metaDataContext->parentClassifier = UA_NS0ID_PUBLISHEDDATAITEMSTYPE;
metaDataContext->elementClassiefier = UA_NS0ID_PUBLISHEDDATAITEMSTYPE_DATASETMETADATA;
- retVal |= addVariableValueSource(server, valueCallback, dataSetMetaDataNode, metaDataContext);
+ retVal |= addVariableValueSource(server, valueCallback,
+ dataSetMetaDataNode, metaDataContext);
#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL_METHODS
retVal |= UA_Server_addReference(server, publishedDataSet->identifier,
@@ -31837,7 +34101,7 @@ addPublishedDataItemsAction(UA_Server *server,
size_t fieldFlagsSize = input[2].arrayLength;
UA_DataSetFieldFlags * fieldFlags = (UA_DataSetFieldFlags *) input[2].data;
size_t variablesToAddSize = input[3].arrayLength;
- UA_PublishedVariableDataType *variablesToAddField = (UA_PublishedVariableDataType *) input[3].data;
+ UA_ExtensionObject *eoAddVar = (UA_ExtensionObject *)input[3].data;
if(!(fieldNameAliasesSize == fieldFlagsSize || fieldFlagsSize == variablesToAddSize))
return UA_STATUSCODE_BADINVALIDARGUMENT;
@@ -31848,20 +34112,43 @@ addPublishedDataItemsAction(UA_Server *server,
publishedDataSetConfig.publishedDataSetType = UA_PUBSUB_DATASET_PUBLISHEDITEMS;
UA_NodeId dataSetItemsNodeId;
- retVal |= UA_Server_addPublishedDataSet(server, &publishedDataSetConfig, &dataSetItemsNodeId).addResult;
+ retVal |= UA_Server_addPublishedDataSet(server, &publishedDataSetConfig,
+ &dataSetItemsNodeId).addResult;
+ if(retVal != UA_STATUSCODE_GOOD) {
+ UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "addPublishedDataset failed");
+ return retVal;
+ }
UA_DataSetFieldConfig dataSetFieldConfig;
for(size_t j = 0; j < variablesToAddSize; ++j) {
- memset(&dataSetFieldConfig, 0, sizeof(dataSetFieldConfig));
+ memset(&dataSetFieldConfig, 0, sizeof(UA_DataSetFieldConfig));
dataSetFieldConfig.dataSetFieldType = UA_PUBSUB_DATASETFIELD_VARIABLE;
dataSetFieldConfig.field.variable.fieldNameAlias = fieldNameAliases[j];
- if(fieldFlags[j] == UA_DATASETFIELDFLAGS_PROMOTEDFIELD){
- dataSetFieldConfig.field.variable.promotedField = UA_TRUE;
+ if(fieldFlags[j] == UA_DATASETFIELDFLAGS_PROMOTEDFIELD)
+ dataSetFieldConfig.field.variable.promotedField = true;
+
+ UA_PublishedVariableDataType variablesToAddField;
+ UA_PublishedVariableDataType_init(&variablesToAddField);
+ if(eoAddVar[j].encoding == UA_EXTENSIONOBJECT_DECODED){
+ if(eoAddVar[j].content.decoded.type == &UA_TYPES[UA_TYPES_PUBLISHEDVARIABLEDATATYPE]){
+ if(UA_PublishedVariableDataType_copy((UA_PublishedVariableDataType *) eoAddVar[j].content.decoded.data,
+ &variablesToAddField) != UA_STATUSCODE_GOOD){
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ }
+ }
}
- dataSetFieldConfig.field.variable.publishParameters = variablesToAddField[j];
- UA_Server_addDataSetField(server, dataSetItemsNodeId, &dataSetFieldConfig, NULL);
+ dataSetFieldConfig.field.variable.publishParameters = variablesToAddField;
+ retVal |= UA_Server_addDataSetField(server, dataSetItemsNodeId, &dataSetFieldConfig, NULL).result;
+ if(retVal != UA_STATUSCODE_GOOD) {
+ UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER, "addDataSetField failed");
+ return retVal;
+ }
+
+ UA_PublishedVariableDataType_clear(&variablesToAddField);
}
- UA_PublishedVariableDataType_clear(variablesToAddField);
+
+ UA_Variant_setScalarCopy(output, &dataSetItemsNodeId, &UA_TYPES[UA_TYPES_NODEID]);
return retVal;
}
#endif
@@ -31874,9 +34161,7 @@ addVariablesAction(UA_Server *server,
const UA_NodeId *objectId, void *objectContext,
size_t inputSize, const UA_Variant *input,
size_t outputSize, UA_Variant *output){
- UA_StatusCode retVal = UA_STATUSCODE_GOOD;
-
- return retVal;
+ return UA_STATUSCODE_GOOD;
}
static UA_StatusCode
@@ -31886,19 +34171,15 @@ removeVariablesAction(UA_Server *server,
const UA_NodeId *objectId, void *objectContext,
size_t inputSize, const UA_Variant *input,
size_t outputSize, UA_Variant *output){
- UA_StatusCode retVal = UA_STATUSCODE_GOOD;
-
- return retVal;
+ return UA_STATUSCODE_GOOD;
}
#endif
UA_StatusCode
-removePublishedDataSetRepresentation(UA_Server *server, UA_PublishedDataSet *publishedDataSet){
- UA_StatusCode retVal = UA_STATUSCODE_GOOD;
- retVal |= UA_Server_deleteNode(server, publishedDataSet->identifier, false);
-
- return retVal;
+removePublishedDataSetRepresentation(UA_Server *server,
+ UA_PublishedDataSet *publishedDataSet) {
+ return UA_Server_deleteNode(server, publishedDataSet->identifier, true);
}
#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL_METHODS
@@ -31909,10 +34190,8 @@ removePublishedDataSetAction(UA_Server *server,
const UA_NodeId *objectId, void *objectContext,
size_t inputSize, const UA_Variant *input,
size_t outputSize, UA_Variant *output){
- UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_NodeId nodeToRemove = *((UA_NodeId *) input[0].data);
- retVal |= UA_Server_removePublishedDataSet(server, nodeToRemove);
- return retVal;
+ return UA_Server_removePublishedDataSet(server, nodeToRemove);
}
#endif
@@ -31969,25 +34248,29 @@ addWriterGroupRepresentation(UA_Server *server, UA_WriterGroup *writerGroup){
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
if(writerGroup->config.name.length > 512)
return UA_STATUSCODE_BADOUTOFMEMORY;
- UA_STACKARRAY(char, wgName, sizeof(char) * writerGroup->config.name.length + 1);
+ char wgName[513];
memcpy(wgName, writerGroup->config.name.data, writerGroup->config.name.length);
wgName[writerGroup->config.name.length] = '\0';
- //This code block must use a lock
- UA_NODESTORE_REMOVE(server, &writerGroup->identifier);
- retVal |= addPubSubObjectNode(server, wgName, writerGroup->identifier.identifier.numeric,
- writerGroup->linkedConnection->identifier.identifier.numeric,
- UA_NS0ID_HASCOMPONENT, UA_NS0ID_WRITERGROUPTYPE);
- //End lock zone
+
+ UA_ObjectAttributes object_attr = UA_ObjectAttributes_default;
+ object_attr.displayName = UA_LOCALIZEDTEXT("", wgName);
+ retVal = UA_Server_addObjectNode(server, UA_NODEID_NUMERIC(1, 0), /* create a new id */
+ writerGroup->linkedConnection->identifier,
+ UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
+ UA_QUALIFIEDNAME(0, wgName),
+ UA_NODEID_NUMERIC(0, UA_NS0ID_WRITERGROUPTYPE),
+ object_attr, NULL, &writerGroup->identifier);
+
UA_NodeId keepAliveNode =
findSingleChildNode(server, UA_QUALIFIEDNAME(0, "KeepAliveTime"),
UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY),
- UA_NODEID_NUMERIC(0, writerGroup->identifier.identifier.numeric));
+ writerGroup->identifier);
UA_NodeId publishingIntervalNode =
findSingleChildNode(server, UA_QUALIFIEDNAME(0, "PublishingInterval"),
UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY),
- UA_NODEID_NUMERIC(0, writerGroup->identifier.identifier.numeric));
- if(UA_NodeId_equal(&keepAliveNode, &UA_NODEID_NULL) ||
- UA_NodeId_equal(&publishingIntervalNode, &UA_NODEID_NULL))
+ writerGroup->identifier);
+ if(UA_NodeId_isNull(&keepAliveNode) ||
+ UA_NodeId_isNull(&publishingIntervalNode))
return UA_STATUSCODE_BADNOTFOUND;
UA_NodePropertyContext * publishingIntervalContext = (UA_NodePropertyContext *)
@@ -32006,11 +34289,12 @@ addWriterGroupRepresentation(UA_Server *server, UA_WriterGroup *writerGroup){
UA_NodeId priorityNode =
findSingleChildNode(server, UA_QUALIFIEDNAME(0, "Priority"),
UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY),
- UA_NODEID_NUMERIC(0, writerGroup->identifier.identifier.numeric));
+ writerGroup->identifier);
UA_NodeId writerGroupIdNode =
findSingleChildNode(server, UA_QUALIFIEDNAME(0, "WriterGroupId"),
UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY),
- UA_NODEID_NUMERIC(0, writerGroup->identifier.identifier.numeric));
+ writerGroup->identifier);
+
UA_Variant value;
UA_Variant_init(&value);
UA_Variant_setScalar(&value, &writerGroup->config.publishingInterval, &UA_TYPES[UA_TYPES_DURATION]);
@@ -32022,34 +34306,46 @@ addWriterGroupRepresentation(UA_Server *server, UA_WriterGroup *writerGroup){
UA_Variant_setScalar(&value, &writerGroup->config.writerGroupId, &UA_TYPES[UA_TYPES_UINT16]);
UA_Server_writeValue(server, writerGroupIdNode, value);
- retVal |= addPubSubObjectNode(server, "MessageSettings", 0,
- writerGroup->identifier.identifier.numeric,
- UA_NS0ID_HASCOMPONENT, UA_NS0ID_UADPWRITERGROUPMESSAGETYPE);
+ object_attr.displayName = UA_LOCALIZEDTEXT("", "MessageSettings");
+ retVal |= UA_Server_addObjectNode(server, UA_NODEID_NUMERIC(1, 0),
+ writerGroup->identifier,
+ UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
+ UA_QUALIFIEDNAME(0, "MessageSettings"),
+ UA_NODEID_NUMERIC(0, UA_NS0ID_UADPWRITERGROUPMESSAGETYPE),
+ object_attr, NULL, NULL);
/* Find the variable with the content mask */
UA_NodeId messageSettingsId =
findSingleChildNode(server, UA_QUALIFIEDNAME(0, "MessageSettings"),
UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
- UA_NODEID_NUMERIC(0, writerGroup->identifier.identifier.numeric));
+ writerGroup->identifier);
UA_NodeId contentMaskId =
findSingleChildNode(server, UA_QUALIFIEDNAME(0, "NetworkMessageContentMask"),
UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY), messageSettingsId);
- if(UA_NodeId_equal(&messageSettingsId, &UA_NODEID_NULL) ||
- UA_NodeId_equal(&contentMaskId, &UA_NODEID_NULL)) {
- return UA_STATUSCODE_BADNOTFOUND;
- }
+ if(!UA_NodeId_isNull(&contentMaskId)) {
+ /* Set the callback */
+ UA_DataSource ds;
+ ds.read = readContentMask;
+ ds.write = writeContentMask;
+ UA_Server_setVariableNode_dataSource(server, contentMaskId, ds);
+ UA_Server_setNodeContext(server, contentMaskId, writerGroup);
+
+ /* Make writable */
+ UA_Server_writeAccessLevel(server, contentMaskId,
+ UA_ACCESSLEVELMASK_WRITE | UA_ACCESSLEVELMASK_READ);
- /* Set the callback */
- UA_DataSource ds;
- ds.read = readContentMask;
- ds.write = writeContentMask;
- UA_Server_setVariableNode_dataSource(server, contentMaskId, ds);
- UA_Server_setNodeContext(server, contentMaskId, writerGroup);
+ }
- /* Make writable */
- UA_Server_writeAccessLevel(server, contentMaskId,
- UA_ACCESSLEVELMASK_WRITE | UA_ACCESSLEVELMASK_READ);
+ /* Add reference to methods */
+#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL_METHODS
+ retVal |= UA_Server_addReference(server, writerGroup->identifier,
+ UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
+ UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_WRITERGROUPTYPE_ADDDATASETWRITER), true);
+ retVal |= UA_Server_addReference(server, writerGroup->identifier,
+ UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
+ UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_WRITERGROUPTYPE_REMOVEDATASETWRITER), true);
+#endif
return retVal;
}
@@ -32064,55 +34360,81 @@ addWriterGroupAction(UA_Server *server,
size_t outputSize, UA_Variant *output){
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_WriterGroupDataType *writerGroupDataType = ((UA_WriterGroupDataType *) input[0].data);
- UA_NodeId generatedId;
- UA_WriterGroupConfig writerGroupConfig;
- memset(&writerGroupConfig, 0, sizeof(UA_WriterGroupConfig));
- writerGroupConfig.name = writerGroupDataType->name;
- writerGroupConfig.publishingInterval = writerGroupDataType->publishingInterval;
- writerGroupConfig.writerGroupId = writerGroupDataType->writerGroupId;
- writerGroupConfig.enabled = writerGroupDataType->enabled;
- writerGroupConfig.priority = writerGroupDataType->priority;
- //TODO remove hard coded UADP
- writerGroupConfig.encodingMimeType = UA_PUBSUB_ENCODING_UADP;
- //ToDo transfer all arguments to internal WGConfiguration
- retVal |= UA_Server_addWriterGroup(server, *objectId, &writerGroupConfig, &generatedId);
- UA_Variant_setScalarCopy(output, &generatedId, &UA_TYPES[UA_TYPES_NODEID]);
+ UA_NodeId writerGroupId;
+ retVal |= addWriterGroupConfig(server, *objectId, writerGroupDataType, &writerGroupId);
+ if(retVal != UA_STATUSCODE_GOOD) {
+ UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER, "addWriterGroup failed");
+ return retVal;
+ }
+ //TODO: Need to handle the UA_Server_setWriterGroupOperational based on the status variable in information model
+
+ UA_Variant_setScalarCopy(output, &writerGroupId, &UA_TYPES[UA_TYPES_NODEID]);
return retVal;
}
#endif
UA_StatusCode
removeGroupRepresentation(UA_Server *server, UA_WriterGroup *writerGroup) {
- UA_StatusCode retVal = UA_STATUSCODE_GOOD;
- retVal |= UA_Server_deleteNode(server, writerGroup->identifier, false);
- return retVal;
+ return UA_Server_deleteNode(server, writerGroup->identifier, true);
+}
+
+UA_StatusCode
+removeReaderGroupRepresentation(UA_Server *server, UA_ReaderGroup *readerGroup) {
+ return UA_Server_deleteNode(server, readerGroup->identifier, true);
}
#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL_METHODS
static UA_StatusCode
removeGroupAction(UA_Server *server,
- const UA_NodeId *sessionId, void *sessionHandle,
- const UA_NodeId *methodId, void *methodContext,
- const UA_NodeId *objectId, void *objectContext,
- size_t inputSize, const UA_Variant *input,
- size_t outputSize, UA_Variant *output){
- UA_StatusCode retVal = UA_STATUSCODE_GOOD;
- UA_NodeId nodeToRemove = *((UA_NodeId *) input[0].data);
- if(UA_WriterGroup_findWGbyId(server, nodeToRemove) != NULL)
- retVal |= UA_Server_removeWriterGroup(server, nodeToRemove);
- //else
- //retVal |= UA_Server_removeReaderGroup(server, nodeToRemve);
- return retVal;
+ const UA_NodeId *sessionId, void *sessionHandle,
+ const UA_NodeId *methodId, void *methodContext,
+ const UA_NodeId *objectId, void *objectContext,
+ size_t inputSize, const UA_Variant *input,
+ size_t outputSize, UA_Variant *output){
+ UA_NodeId nodeToRemove = *((UA_NodeId *)input->data);
+ if(UA_WriterGroup_findWGbyId(server, nodeToRemove)) {
+ UA_WriterGroup *wg = UA_WriterGroup_findWGbyId(server, nodeToRemove);
+ if(wg->configurationFrozen)
+ UA_Server_unfreezeWriterGroupConfiguration(server, nodeToRemove);
+ return UA_Server_removeWriterGroup(server, nodeToRemove);
+ } else {
+ UA_ReaderGroup *rg = UA_ReaderGroup_findRGbyId(server, nodeToRemove);
+ if(rg->configurationFrozen)
+ UA_Server_unfreezeReaderGroupConfiguration(server, nodeToRemove);
+ return UA_Server_removeReaderGroup(server, nodeToRemove);
+ }
}
#endif
/**********************************************/
/* ReaderGroup */
/**********************************************/
+
UA_StatusCode
-addReaderGroupRepresentation(UA_Server *server, UA_ReaderGroup *readerGroup){
- //TODO implement reader part
- return UA_STATUSCODE_BADNOTIMPLEMENTED;
+addReaderGroupRepresentation(UA_Server *server, UA_ReaderGroup *readerGroup) {
+ if(readerGroup->config.name.length > 512)
+ return UA_STATUSCODE_BADCONFIGURATIONERROR;
+ char rgName[513];
+ memcpy(rgName, readerGroup->config.name.data, readerGroup->config.name.length);
+ rgName[readerGroup->config.name.length] = '\0';
+
+ UA_ObjectAttributes object_attr = UA_ObjectAttributes_default;
+ object_attr.displayName = UA_LOCALIZEDTEXT("", rgName);
+ UA_StatusCode retVal = UA_Server_addObjectNode(server, UA_NODEID_NUMERIC(1, 0), /* create an id */
+ readerGroup->linkedConnection,
+ UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
+ UA_QUALIFIEDNAME(0, rgName),
+ UA_NODEID_NUMERIC(0, UA_NS0ID_READERGROUPTYPE),
+ object_attr, NULL, &readerGroup->identifier);
+#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL_METHODS
+ retVal |= UA_Server_addReference(server, readerGroup->identifier,
+ UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
+ UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_READERGROUPTYPE_ADDDATASETREADER), true);
+ retVal |= UA_Server_addReference(server, readerGroup->identifier,
+ UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
+ UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_READERGROUPTYPE_REMOVEDATASETREADER), true);
+#endif
+ return retVal;
}
#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL_METHODS
@@ -32124,7 +34446,16 @@ addReaderGroupAction(UA_Server *server,
size_t inputSize, const UA_Variant *input,
size_t outputSize, UA_Variant *output){
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
- //TODO implement reader part
+ UA_ReaderGroupDataType *readerGroupDataType = ((UA_ReaderGroupDataType *) input->data);
+ UA_NodeId readerGroupId;
+ retVal |= addReaderGroupConfig(server, *objectId, readerGroupDataType, &readerGroupId);
+ if(retVal != UA_STATUSCODE_GOOD) {
+ UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER, "addReaderGroup failed");
+ return retVal;
+ }
+ //TODO: Need to handle the UA_Server_setReaderGroupOperational based on the status variable in information model
+
+ UA_Variant_setScalarCopy(output, &readerGroupId, &UA_TYPES[UA_TYPES_NODEID]);
return retVal;
}
#endif
@@ -32132,28 +34463,73 @@ addReaderGroupAction(UA_Server *server,
/**********************************************/
/* DataSetWriter */
/**********************************************/
+
UA_StatusCode
addDataSetWriterRepresentation(UA_Server *server, UA_DataSetWriter *dataSetWriter){
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
if(dataSetWriter->config.name.length > 512)
return UA_STATUSCODE_BADOUTOFMEMORY;
- UA_STACKARRAY(char, dswName, sizeof(char) * dataSetWriter->config.name.length + 1);
+ char dswName[513];
memcpy(dswName, dataSetWriter->config.name.data, dataSetWriter->config.name.length);
dswName[dataSetWriter->config.name.length] = '\0';
- //This code block must use a lock
- UA_NODESTORE_REMOVE(server, &dataSetWriter->identifier);
- retVal |= addPubSubObjectNode(server, dswName, dataSetWriter->identifier.identifier.numeric,
- dataSetWriter->linkedWriterGroup.identifier.numeric,
- UA_NS0ID_HASDATASETWRITER, UA_NS0ID_DATASETWRITERTYPE);
- //End lock zone
+
+ UA_ObjectAttributes object_attr = UA_ObjectAttributes_default;
+ object_attr.displayName = UA_LOCALIZEDTEXT("", dswName);
+ retVal = UA_Server_addObjectNode(server, UA_NODEID_NUMERIC(1, 0), /* create an id */
+ dataSetWriter->linkedWriterGroup,
+ UA_NODEID_NUMERIC(0, UA_NS0ID_HASDATASETWRITER),
+ UA_QUALIFIEDNAME(0, dswName),
+ UA_NODEID_NUMERIC(0, UA_NS0ID_DATASETWRITERTYPE),
+ object_attr, NULL, &dataSetWriter->identifier);
+
retVal |= UA_Server_addReference(server, dataSetWriter->connectedDataSet,
UA_NODEID_NUMERIC(0, UA_NS0ID_DATASETTOWRITER),
- UA_EXPANDEDNODEID_NUMERIC(0, dataSetWriter->identifier.identifier.numeric), true);
+ UA_EXPANDEDNODEID_NODEID(dataSetWriter->identifier),
+ true);
+ UA_NodeId dataSetWriterIdNode =
+ findSingleChildNode(server, UA_QUALIFIEDNAME(0, "DataSetWriterId"),
+ UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY),
+ dataSetWriter->identifier);
+ UA_NodeId keyFrameNode =
+ findSingleChildNode(server, UA_QUALIFIEDNAME(0, "KeyFrameCount"),
+ UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY),
+ dataSetWriter->identifier);
+ UA_NodeId dataSetFieldContentMaskNode =
+ findSingleChildNode(server, UA_QUALIFIEDNAME(0, "DataSetFieldContentMask"),
+ UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY),
+ dataSetWriter->identifier);
- retVal |= addPubSubObjectNode(server, "MessageSettings", 0,
- dataSetWriter->identifier.identifier.numeric,
- UA_NS0ID_HASCOMPONENT, UA_NS0ID_UADPDATASETWRITERMESSAGETYPE);
+ UA_NodePropertyContext *dataSetWriterIdContext = (UA_NodePropertyContext *)
+ UA_malloc(sizeof(UA_NodePropertyContext));
+ dataSetWriterIdContext->parentNodeId = dataSetWriter->identifier;
+ dataSetWriterIdContext->parentClassifier = UA_NS0ID_DATASETWRITERTYPE;
+ dataSetWriterIdContext->elementClassiefier = UA_NS0ID_DATASETWRITERTYPE_DATASETWRITERID;
+ UA_ValueCallback valueCallback;
+ valueCallback.onRead = onRead;
+ valueCallback.onWrite = NULL;
+ retVal |= addVariableValueSource(server, valueCallback,
+ dataSetWriterIdNode, dataSetWriterIdContext);
+
+ UA_Variant value;
+ UA_Variant_init(&value);
+ UA_Variant_setScalar(&value, &dataSetWriter->config.dataSetWriterId,
+ &UA_TYPES[UA_TYPES_UINT16]);
+ UA_Server_writeValue(server, dataSetWriterIdNode, value);
+ UA_Variant_setScalar(&value, &dataSetWriter->config.keyFrameCount,
+ &UA_TYPES[UA_TYPES_UINT32]);
+ UA_Server_writeValue(server, keyFrameNode, value);
+ UA_Variant_setScalar(&value, &dataSetWriter->config.dataSetFieldContentMask,
+ &UA_TYPES[UA_TYPES_DATASETFIELDCONTENTMASK]);
+ UA_Server_writeValue(server, dataSetFieldContentMaskNode, value);
+
+ object_attr.displayName = UA_LOCALIZEDTEXT("", "MessageSettings");
+ retVal |= UA_Server_addObjectNode(server, UA_NODEID_NUMERIC(1, 0),
+ dataSetWriter->identifier,
+ UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
+ UA_QUALIFIEDNAME(0, "MessageSettings"),
+ UA_NODEID_NUMERIC(0, UA_NS0ID_UADPDATASETWRITERMESSAGETYPE),
+ object_attr, NULL, NULL);
return retVal;
}
@@ -32165,39 +34541,38 @@ addDataSetWriterAction(UA_Server *server,
const UA_NodeId *objectId, void *objectContext,
size_t inputSize, const UA_Variant *input,
size_t outputSize, UA_Variant *output){
- UA_DataSetWriterDataType *dataSetWriterDataType = (UA_DataSetWriterDataType *) input[0].data;
-
- UA_NodeId targetPDS = UA_NODEID_NULL;
- UA_PublishedDataSet *tmpPDS;
- TAILQ_FOREACH(tmpPDS, &server->pubSubManager.publishedDataSets, listEntry){
- if(UA_String_equal(&dataSetWriterDataType->dataSetName, &tmpPDS->config.name)){
- targetPDS = tmpPDS->identifier;
- }
+ UA_StatusCode retVal = UA_STATUSCODE_GOOD;
+ UA_WriterGroup *wg = UA_WriterGroup_findWGbyId(server, *objectId);
+ if(!wg) {
+ UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Not a WriterGroup");
+ return UA_STATUSCODE_BAD;
+ }
+ if(wg->configurationFrozen) {
+ UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "addDataSetWriter cannot be done because writergroup config frozen");
+ return UA_STATUSCODE_BAD;
}
- if(UA_NodeId_isNull(&targetPDS))
- return UA_STATUSCODE_BADPARENTNODEIDINVALID;
-
- UA_NodeId generatedId;
- UA_DataSetWriterConfig dataSetWriterConfig;
- memset(&dataSetWriterConfig, 0, sizeof(UA_DataSetWriterConfig));
- dataSetWriterConfig.name = dataSetWriterDataType->name;
- dataSetWriterConfig.dataSetName = dataSetWriterDataType->dataSetName;
- dataSetWriterConfig.keyFrameCount = dataSetWriterDataType->keyFrameCount;
- dataSetWriterConfig.dataSetWriterId = dataSetWriterDataType->dataSetWriterId;
+ UA_NodeId dataSetWriterId;
+ UA_DataSetWriterDataType *dataSetWriterData = (UA_DataSetWriterDataType *)input->data;
+ retVal |= addDataSetWriterConfig(server, objectId, dataSetWriterData, &dataSetWriterId);
+ if(retVal != UA_STATUSCODE_GOOD) {
+ UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "addDataSetWriter failed");
+ return retVal;
+ }
- UA_Server_addDataSetWriter(server, *objectId, targetPDS, &dataSetWriterConfig, &generatedId);
- UA_Variant_setScalarCopy(output, &generatedId, &UA_TYPES[UA_TYPES_NODEID]);
+ UA_Variant_setScalarCopy(output, &dataSetWriterId, &UA_TYPES[UA_TYPES_NODEID]);
return UA_STATUSCODE_GOOD;
}
#endif
UA_StatusCode
-removeDataSetWriterRepresentation(UA_Server *server, UA_DataSetWriter *dataSetWriter) {
- UA_StatusCode retVal = UA_STATUSCODE_GOOD;
- retVal |= UA_Server_deleteNode(server, dataSetWriter->identifier, false);
- return retVal;
+removeDataSetWriterRepresentation(UA_Server *server,
+ UA_DataSetWriter *dataSetWriter) {
+ return UA_Server_deleteNode(server, dataSetWriter->identifier, true);
}
#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL_METHODS
@@ -32208,10 +34583,8 @@ removeDataSetWriterAction(UA_Server *server,
const UA_NodeId *objectId, void *objectContext,
size_t inputSize, const UA_Variant *input,
size_t outputSize, UA_Variant *output){
- UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_NodeId nodeToRemove = *((UA_NodeId *) input[0].data);
- retVal |= UA_Server_removeDataSetWriter(server, nodeToRemove);
- return retVal;
+ return UA_Server_removeDataSetWriter(server, nodeToRemove);
}
#endif
@@ -32224,16 +34597,15 @@ connectionTypeDestructor(UA_Server *server,
const UA_NodeId *sessionId, void *sessionContext,
const UA_NodeId *typeId, void *typeContext,
const UA_NodeId *nodeId, void **nodeContext) {
- UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_USERLAND, "Connection destructor called!");
- UA_NodeId publisherIdNode;
- publisherIdNode = findSingleChildNode(server, UA_QUALIFIEDNAME(0, "PublisherId"),
- UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY), *nodeId);
- UA_NodePropertyContext *internalConnectionContext;
- UA_Server_getNodeContext(server, publisherIdNode, (void **) &internalConnectionContext);
- if(!UA_NodeId_equal(&UA_NODEID_NULL , &publisherIdNode)){
- UA_free(internalConnectionContext);
- }
-
+ UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_USERLAND,
+ "Connection destructor called!");
+ UA_NodeId publisherIdNode =
+ findSingleChildNode(server, UA_QUALIFIEDNAME(0, "PublisherId"),
+ UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY), *nodeId);
+ UA_NodePropertyContext *ctx;
+ UA_Server_getNodeContext(server, publisherIdNode, (void **)&ctx);
+ if(!UA_NodeId_isNull(&publisherIdNode))
+ UA_free(ctx);
}
static void
@@ -32241,15 +34613,15 @@ writerGroupTypeDestructor(UA_Server *server,
const UA_NodeId *sessionId, void *sessionContext,
const UA_NodeId *typeId, void *typeContext,
const UA_NodeId *nodeId, void **nodeContext) {
- UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_USERLAND, "WriterGroup destructor called!");
- UA_NodeId intervalNode;
- intervalNode = findSingleChildNode(server, UA_QUALIFIEDNAME(0, "PublishingInterval"),
- UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY), *nodeId);
- UA_NodePropertyContext *internalConnectionContext;
- UA_Server_getNodeContext(server, intervalNode, (void **) &internalConnectionContext);
- if(!UA_NodeId_equal(&UA_NODEID_NULL , &intervalNode)){
- UA_free(internalConnectionContext);
- }
+ UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_USERLAND,
+ "WriterGroup destructor called!");
+ UA_NodeId intervalNode =
+ findSingleChildNode(server, UA_QUALIFIEDNAME(0, "PublishingInterval"),
+ UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY), *nodeId);
+ UA_NodePropertyContext *ctx;
+ UA_Server_getNodeContext(server, intervalNode, (void **)&ctx);
+ if(!UA_NodeId_isNull(&intervalNode))
+ UA_free(ctx);
}
static void
@@ -32257,7 +34629,8 @@ readerGroupTypeDestructor(UA_Server *server,
const UA_NodeId *sessionId, void *sessionContext,
const UA_NodeId *typeId, void *typeContext,
const UA_NodeId *nodeId, void **nodeContext) {
- UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_USERLAND, "ReaderGroup destructor called!");
+ UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_USERLAND,
+ "ReaderGroup destructor called!");
}
static void
@@ -32265,7 +34638,15 @@ dataSetWriterTypeDestructor(UA_Server *server,
const UA_NodeId *sessionId, void *sessionContext,
const UA_NodeId *typeId, void *typeContext,
const UA_NodeId *nodeId, void **nodeContext) {
- UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_USERLAND, "DataSetWriter destructor called!");
+ UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_USERLAND,
+ "DataSetWriter destructor called!");
+ UA_NodeId dataSetWriterIdNode =
+ findSingleChildNode(server, UA_QUALIFIEDNAME(0, "DataSetWriterId"),
+ UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY), *nodeId);
+ UA_NodePropertyContext *ctx;
+ UA_Server_getNodeContext(server, dataSetWriterIdNode, (void **)&ctx);
+ if(!UA_NodeId_isNull(&dataSetWriterIdNode))
+ UA_free(ctx);
}
static void
@@ -32273,7 +34654,17 @@ dataSetReaderTypeDestructor(UA_Server *server,
const UA_NodeId *sessionId, void *sessionContext,
const UA_NodeId *typeId, void *typeContext,
const UA_NodeId *nodeId, void **nodeContext) {
- UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_USERLAND, "DataSetReader destructor called!");
+ UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_USERLAND,
+ "DataSetReader destructor called!");
+
+ /* Deallocate the memory allocated for publisherId */
+ UA_NodeId publisherIdNode =
+ findSingleChildNode(server, UA_QUALIFIEDNAME(0, "PublisherId"),
+ UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY), *nodeId);
+ UA_NodePropertyContext *ctx;
+ UA_Server_getNodeContext(server, publisherIdNode, (void **)&ctx);
+ if(!UA_NodeId_isNull(&publisherIdNode))
+ UA_free(ctx);
}
static void
@@ -32287,23 +34678,104 @@ publishedDataItemsTypeDestructor(UA_Server *server,
UA_NodeId node = findSingleChildNode(server, UA_QUALIFIEDNAME(0, "PublishedData"),
UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY), *nodeId);
UA_Server_getNodeContext(server, node, (void**)&childContext);
- if(!UA_NodeId_equal(&UA_NODEID_NULL , &node))
+ if(!UA_NodeId_isNull(&node))
UA_free(childContext);
node = findSingleChildNode(server, UA_QUALIFIEDNAME(0, "ConfigurationVersion"),
UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY),
*nodeId);
UA_Server_getNodeContext(server, node, (void**)&childContext);
- if(!UA_NodeId_equal(&UA_NODEID_NULL , &node))
+ if(!UA_NodeId_isNull(&node))
UA_free(childContext);
node = findSingleChildNode(server, UA_QUALIFIEDNAME(0, "DataSetMetaData"),
UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY), *nodeId);
UA_Server_getNodeContext(server, node, (void**)&childContext);
- if(!UA_NodeId_equal(&node, &UA_NODEID_NULL))
+ if(!UA_NodeId_isNull(&node))
UA_free(childContext);
}
+/*************************************/
+/* PubSub configurator */
+/*************************************/
+
+#if defined(UA_ENABLE_PUBSUB_INFORMATIONMODEL_METHODS) && defined(UA_ENABLE_PUBSUB_FILE_CONFIG)
+
+/* Callback function that will be executed when the method "PubSub configurator
+ * (replace config)" is called. */
+static UA_StatusCode
+UA_loadPubSubConfigMethodCallback(UA_Server *server,
+ const UA_NodeId *sessionId, void *sessionHandle,
+ const UA_NodeId *methodId, void *methodContext,
+ const UA_NodeId *objectId, void *objectContext,
+ size_t inputSize, const UA_Variant *input,
+ size_t outputSize, UA_Variant *output) {
+ if(inputSize == 1) {
+ UA_ByteString *inputStr = (UA_ByteString*)input->data;
+ return UA_PubSubManager_loadPubSubConfigFromByteString(server, *inputStr);
+ } else if(inputSize > 1) {
+ return UA_STATUSCODE_BADTOOMANYARGUMENTS;
+ } else {
+ return UA_STATUSCODE_BADARGUMENTSMISSING;
+ }
+}
+
+/* Adds method node to server. This method is used to load binary files for
+ * PubSub configuration and delete / replace old PubSub configurations. */
+static UA_StatusCode
+UA_addLoadPubSubConfigMethod(UA_Server *server) {
+ UA_Argument inputArgument;
+ UA_Argument_init(&inputArgument);
+ inputArgument.description = UA_LOCALIZEDTEXT("", "PubSub config binfile");
+ inputArgument.name = UA_STRING("BinFile");
+ inputArgument.dataType = UA_TYPES[UA_TYPES_BYTESTRING].typeId;
+ inputArgument.valueRank = UA_VALUERANK_SCALAR;
+
+ UA_MethodAttributes configAttr = UA_MethodAttributes_default;
+ configAttr.description = UA_LOCALIZEDTEXT("","Load binary configuration file");
+ configAttr.displayName = UA_LOCALIZEDTEXT("","LoadPubSubConfigurationFile");
+ configAttr.executable = true;
+ configAttr.userExecutable = true;
+ return UA_Server_addMethodNode(server, UA_NODEID_NULL,
+ UA_NODEID_NUMERIC(0, UA_NS0ID_PUBLISHSUBSCRIBE),
+ UA_NODEID_NUMERIC(0, UA_NS0ID_HASORDEREDCOMPONENT),
+ UA_QUALIFIEDNAME(1, "PubSub configuration"),
+ configAttr, &UA_loadPubSubConfigMethodCallback,
+ 1, &inputArgument, 0, NULL, NULL, NULL);
+}
+
+/* Callback function that will be executed when the method "PubSub configurator
+ * (delete config)" is called. */
+static UA_StatusCode
+UA_deletePubSubConfigMethodCallback(UA_Server *server,
+ const UA_NodeId *sessionId, void *sessionHandle,
+ const UA_NodeId *methodId, void *methodContext,
+ const UA_NodeId *objectId, void *objectContext,
+ size_t inputSize, const UA_Variant *input,
+ size_t outputSize, UA_Variant *output) {
+ UA_PubSubManager_delete(server, &(server->pubSubManager));
+ return UA_STATUSCODE_GOOD;
+}
+
+/* Adds method node to server. This method is used to delete the current PubSub
+ * configuration. */
+static UA_StatusCode
+UA_addDeletePubSubConfigMethod(UA_Server *server) {
+ UA_MethodAttributes configAttr = UA_MethodAttributes_default;
+ configAttr.description = UA_LOCALIZEDTEXT("","Delete current PubSub configuration");
+ configAttr.displayName = UA_LOCALIZEDTEXT("","DeletePubSubConfiguration");
+ configAttr.executable = true;
+ configAttr.userExecutable = true;
+ return UA_Server_addMethodNode(server, UA_NODEID_NULL,
+ UA_NODEID_NUMERIC(0, UA_NS0ID_PUBLISHSUBSCRIBE),
+ UA_NODEID_NUMERIC(0, UA_NS0ID_HASORDEREDCOMPONENT),
+ UA_QUALIFIEDNAME(1, "Delete PubSub config"),
+ configAttr, &UA_deletePubSubConfigMethodCallback,
+ 0, NULL, 0, NULL, NULL, NULL);
+}
+
+#endif /* defined(UA_ENABLE_PUBSUB_INFORMATIONMODEL_METHODS) && defined(UA_ENABLE_PUBSUB_FILE_CONFIG) */
+
UA_StatusCode
UA_Server_initPubSubNS0(UA_Server *server) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
@@ -32311,14 +34783,10 @@ UA_Server_initPubSubNS0(UA_Server *server) {
profileArray[0] = UA_STRING("http://opcfoundation.org/UA-Profile/Transport/pubsub-udp-uadp");
retVal |= writePubSubNs0VariableArray(server, UA_NS0ID_PUBLISHSUBSCRIBE_SUPPORTEDTRANSPORTPROFILES,
- profileArray,
- 1, &UA_TYPES[UA_TYPES_STRING]);
+ profileArray, 1, &UA_TYPES[UA_TYPES_STRING]);
#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL_METHODS
- retVal |= UA_Server_setMethodNode_callback(server,
- UA_NODEID_NUMERIC(0, UA_NS0ID_PUBLISHSUBSCRIBE_ADDCONNECTION), addPubSubConnectionAction);
- retVal |= UA_Server_setMethodNode_callback(server,
- UA_NODEID_NUMERIC(0, UA_NS0ID_PUBLISHSUBSCRIBE_REMOVECONNECTION), removeConnectionAction);
+ /* Add missing references */
retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_PUBLISHSUBSCRIBE_PUBLISHEDDATASETS),
UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_DATASETFOLDERTYPE_ADDDATASETFOLDER), true);
@@ -32331,55 +34799,69 @@ UA_Server_initPubSubNS0(UA_Server *server) {
retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_PUBLISHSUBSCRIBE_PUBLISHEDDATASETS),
UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_DATASETFOLDERTYPE_REMOVEDATASETFOLDER), true);
- retVal |= UA_Server_setMethodNode_callback(server,
- UA_NODEID_NUMERIC(0, UA_NS0ID_DATASETFOLDERTYPE_ADDDATASETFOLDER), addDataSetFolderAction);
- retVal |= UA_Server_setMethodNode_callback(server,
- UA_NODEID_NUMERIC(0, UA_NS0ID_DATASETFOLDERTYPE_REMOVEDATASETFOLDER), removeDataSetFolderAction);
- retVal |= UA_Server_setMethodNode_callback(server,
- UA_NODEID_NUMERIC(0, UA_NS0ID_DATASETFOLDERTYPE_ADDPUBLISHEDDATAITEMS), addPublishedDataItemsAction);
- retVal |= UA_Server_setMethodNode_callback(server,
- UA_NODEID_NUMERIC(0, UA_NS0ID_DATASETFOLDERTYPE_REMOVEPUBLISHEDDATASET), removePublishedDataSetAction);
- retVal |= UA_Server_setMethodNode_callback(server,
- UA_NODEID_NUMERIC(0, UA_NS0ID_PUBLISHEDDATAITEMSTYPE_ADDVARIABLES), addVariablesAction);
- retVal |= UA_Server_setMethodNode_callback(server,
- UA_NODEID_NUMERIC(0, UA_NS0ID_PUBLISHEDDATAITEMSTYPE_REMOVEVARIABLES), removeVariablesAction);
- retVal |= UA_Server_setMethodNode_callback(server, UA_NODEID_NUMERIC(0, UA_NS0ID_PUBSUBCONNECTIONTYPE_ADDWRITERGROUP), addWriterGroupAction);
- retVal |= UA_Server_setMethodNode_callback(server, UA_NODEID_NUMERIC(0, UA_NS0ID_PUBSUBCONNECTIONTYPE_ADDREADERGROUP), addReaderGroupAction);
- retVal |= UA_Server_setMethodNode_callback(server, UA_NODEID_NUMERIC(0, UA_NS0ID_PUBSUBCONNECTIONTYPE_REMOVEGROUP), removeGroupAction);
- retVal |= UA_Server_setMethodNode_callback(server, UA_NODEID_NUMERIC(0, UA_NS0ID_WRITERGROUPTYPE_ADDDATASETWRITER), addDataSetWriterAction);
- retVal |= UA_Server_setMethodNode_callback(server, UA_NODEID_NUMERIC(0, UA_NS0ID_WRITERGROUPTYPE_REMOVEDATASETWRITER), removeDataSetWriterAction);
- retVal |= UA_Server_setMethodNode_callback(server, UA_NODEID_NUMERIC(0, UA_NS0ID_READERGROUPTYPE_ADDDATASETREADER), addDataSetReaderAction);
- retVal |= UA_Server_setMethodNode_callback(server, UA_NODEID_NUMERIC(0, UA_NS0ID_READERGROUPTYPE_REMOVEDATASETREADER), removeDataSetReaderAction);
+
+ /* Set method callbacks */
+ retVal |= UA_Server_setMethodNodeCallback(server, UA_NODEID_NUMERIC(0, UA_NS0ID_PUBLISHSUBSCRIBE_ADDCONNECTION), addPubSubConnectionAction);
+ retVal |= UA_Server_setMethodNodeCallback(server, UA_NODEID_NUMERIC(0, UA_NS0ID_PUBLISHSUBSCRIBE_REMOVECONNECTION), removeConnectionAction);
+ retVal |= UA_Server_setMethodNodeCallback(server, UA_NODEID_NUMERIC(0, UA_NS0ID_DATASETFOLDERTYPE_ADDDATASETFOLDER), addDataSetFolderAction);
+ retVal |= UA_Server_setMethodNodeCallback(server, UA_NODEID_NUMERIC(0, UA_NS0ID_DATASETFOLDERTYPE_REMOVEDATASETFOLDER), removeDataSetFolderAction);
+ retVal |= UA_Server_setMethodNodeCallback(server, UA_NODEID_NUMERIC(0, UA_NS0ID_DATASETFOLDERTYPE_ADDPUBLISHEDDATAITEMS), addPublishedDataItemsAction);
+ retVal |= UA_Server_setMethodNodeCallback(server, UA_NODEID_NUMERIC(0, UA_NS0ID_DATASETFOLDERTYPE_REMOVEPUBLISHEDDATASET), removePublishedDataSetAction);
+ retVal |= UA_Server_setMethodNodeCallback(server, UA_NODEID_NUMERIC(0, UA_NS0ID_PUBLISHEDDATAITEMSTYPE_ADDVARIABLES), addVariablesAction);
+ retVal |= UA_Server_setMethodNodeCallback(server, UA_NODEID_NUMERIC(0, UA_NS0ID_PUBLISHEDDATAITEMSTYPE_REMOVEVARIABLES), removeVariablesAction);
+ retVal |= UA_Server_setMethodNodeCallback(server, UA_NODEID_NUMERIC(0, UA_NS0ID_PUBSUBCONNECTIONTYPE_ADDWRITERGROUP), addWriterGroupAction);
+ retVal |= UA_Server_setMethodNodeCallback(server, UA_NODEID_NUMERIC(0, UA_NS0ID_PUBSUBCONNECTIONTYPE_ADDREADERGROUP), addReaderGroupAction);
+ retVal |= UA_Server_setMethodNodeCallback(server, UA_NODEID_NUMERIC(0, UA_NS0ID_PUBSUBCONNECTIONTYPE_REMOVEGROUP), removeGroupAction);
+ retVal |= UA_Server_setMethodNodeCallback(server, UA_NODEID_NUMERIC(0, UA_NS0ID_WRITERGROUPTYPE_ADDDATASETWRITER), addDataSetWriterAction);
+ retVal |= UA_Server_setMethodNodeCallback(server, UA_NODEID_NUMERIC(0, UA_NS0ID_WRITERGROUPTYPE_REMOVEDATASETWRITER), removeDataSetWriterAction);
+ retVal |= UA_Server_setMethodNodeCallback(server, UA_NODEID_NUMERIC(0, UA_NS0ID_READERGROUPTYPE_ADDDATASETREADER), addDataSetReaderAction);
+ retVal |= UA_Server_setMethodNodeCallback(server, UA_NODEID_NUMERIC(0, UA_NS0ID_READERGROUPTYPE_REMOVEDATASETREADER), removeDataSetReaderAction);
+
+#ifdef UA_ENABLE_PUBSUB_FILE_CONFIG
+ retVal |= UA_addLoadPubSubConfigMethod(server);
+ retVal |= UA_addDeletePubSubConfigMethod(server);
+#endif
#else
- retVal |= UA_Server_deleteReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_PUBLISHSUBSCRIBE), UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), true,
+ /* Remove methods */
+ retVal |= UA_Server_deleteReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_PUBLISHSUBSCRIBE),
+ UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), true,
UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_PUBLISHSUBSCRIBE_ADDCONNECTION),
false);
- retVal |= UA_Server_deleteReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_PUBLISHSUBSCRIBE), UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), true,
+ retVal |= UA_Server_deleteReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_PUBLISHSUBSCRIBE),
+ UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), true,
UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_PUBLISHSUBSCRIBE_REMOVECONNECTION),
false);
#endif
- UA_NodeTypeLifecycle liveCycle;
- liveCycle.constructor = NULL;
- liveCycle.destructor = connectionTypeDestructor;
- UA_Server_setNodeTypeLifecycle(server, UA_NODEID_NUMERIC(0, UA_NS0ID_PUBSUBCONNECTIONTYPE), liveCycle);
- liveCycle.destructor = writerGroupTypeDestructor;
- UA_Server_setNodeTypeLifecycle(server, UA_NODEID_NUMERIC(0, UA_NS0ID_WRITERGROUPTYPE), liveCycle);
- liveCycle.destructor = readerGroupTypeDestructor;
- UA_Server_setNodeTypeLifecycle(server, UA_NODEID_NUMERIC(0, UA_NS0ID_READERGROUPTYPE), liveCycle);
- liveCycle.destructor = dataSetWriterTypeDestructor;
- UA_Server_setNodeTypeLifecycle(server, UA_NODEID_NUMERIC(0, UA_NS0ID_DATASETWRITERDATATYPE), liveCycle);
- liveCycle.destructor = publishedDataItemsTypeDestructor;
- UA_Server_setNodeTypeLifecycle(server, UA_NODEID_NUMERIC(0, UA_NS0ID_PUBLISHEDDATAITEMSTYPE), liveCycle);
- liveCycle.destructor = dataSetReaderTypeDestructor;
- UA_Server_setNodeTypeLifecycle(server, UA_NODEID_NUMERIC(0, UA_NS0ID_DATASETREADERDATATYPE), liveCycle);
+
+ /* Set the object-type destructors */
+ UA_NodeTypeLifecycle lifeCycle;
+ lifeCycle.constructor = NULL;
+
+ lifeCycle.destructor = connectionTypeDestructor;
+ retVal |= UA_Server_setNodeTypeLifecycle(server, UA_NODEID_NUMERIC(0, UA_NS0ID_PUBSUBCONNECTIONTYPE), lifeCycle);
+
+ lifeCycle.destructor = writerGroupTypeDestructor;
+ retVal |= UA_Server_setNodeTypeLifecycle(server, UA_NODEID_NUMERIC(0, UA_NS0ID_WRITERGROUPTYPE), lifeCycle);
+
+ lifeCycle.destructor = readerGroupTypeDestructor;
+ retVal |= UA_Server_setNodeTypeLifecycle(server, UA_NODEID_NUMERIC(0, UA_NS0ID_READERGROUPTYPE), lifeCycle);
+
+ lifeCycle.destructor = dataSetWriterTypeDestructor;
+ retVal |= UA_Server_setNodeTypeLifecycle(server, UA_NODEID_NUMERIC(0, UA_NS0ID_DATASETWRITERTYPE), lifeCycle);
+
+ lifeCycle.destructor = publishedDataItemsTypeDestructor;
+ retVal |= UA_Server_setNodeTypeLifecycle(server, UA_NODEID_NUMERIC(0, UA_NS0ID_PUBLISHEDDATAITEMSTYPE), lifeCycle);
+
+ lifeCycle.destructor = dataSetReaderTypeDestructor;
+ retVal |= UA_Server_setNodeTypeLifecycle(server, UA_NODEID_NUMERIC(0, UA_NS0ID_DATASETREADERTYPE), lifeCycle);
return retVal;
}
#endif /* UA_ENABLE_PUBSUB_INFORMATIONMODEL */
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/src/server/ua_services_view.c" ***********************************/
+/**** amalgamated original file "/src/server/ua_services_view.c" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -32400,31 +34882,143 @@ UA_Server_initPubSubNS0(UA_Server *server) {
*/
-/********************/
-/* Browse Recursive */
-/********************/
+#define UA_MAX_TREE_RECURSE 50 /* How deep up/down the tree do we recurse at most? */
-/* A RefTree holds a single array for both the NodeIds encountered during
- * recursive browsing and the entries for a tree-structure to check for
- * duplicates. Once the (recursive) browse has finished, the tree-structure part
- * can be simply cut away. A single realloc operation (with some pointer
- * repairing) can be used to increase the capacity of the RefTree.
- *
- * If an ExpandedNodeId is encountered, it has to be processed right away.
- * Remote ExpandedNodeId are not put into the tree, since it is not possible to
- * recurse into them anyway.
- *
- * The layout of the results array is as follows:
- *
- * | Targets [ExpandedNodeId] | Tree [RefEntry] | */
+UA_StatusCode
+referenceTypeIndices(UA_Server *server, const UA_NodeId *refType,
+ UA_ReferenceTypeSet *indices, UA_Boolean includeSubtypes) {
+ if(UA_NodeId_isNull(refType)) {
+ UA_ReferenceTypeSet_any(indices);
+ return UA_STATUSCODE_GOOD;
+ }
-#define UA_BROWSE_INITIAL_SIZE 16
+ UA_ReferenceTypeSet_init(indices);
+ const UA_Node *refNode = UA_NODESTORE_GET(server, refType);
+ if(!refNode)
+ return UA_STATUSCODE_BADREFERENCETYPEIDINVALID;
-typedef struct RefEntry {
- ZIP_ENTRY(RefEntry) zipfields;
- const UA_ExpandedNodeId *target;
- UA_UInt32 targetHash; /* Hash of the target nodeid */
-} RefEntry;
+ if(refNode->head.nodeClass != UA_NODECLASS_REFERENCETYPE) {
+ UA_NODESTORE_RELEASE(server, refNode);
+ return UA_STATUSCODE_BADREFERENCETYPEIDINVALID;
+ }
+
+ if(!includeSubtypes)
+ *indices = UA_REFTYPESET(refNode->referenceTypeNode.referenceTypeIndex);
+ else
+ *indices = refNode->referenceTypeNode.subTypes;
+
+ UA_NODESTORE_RELEASE(server, refNode);
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_Boolean
+matchClassMask(const UA_Node *node, UA_UInt32 nodeClassMask) {
+ if(nodeClassMask != UA_NODECLASS_UNSPECIFIED &&
+ (node->head.nodeClass & nodeClassMask) == 0)
+ return false;
+ return true;
+}
+
+/****************/
+/* IsNodeInTree */
+/****************/
+
+/* Internal method to check if a node is already upwards from a leaf node */
+
+/* Keeps track of visited nodes to detect circular references */
+struct ref_history {
+ struct ref_history *parent; /* the previous element */
+ const UA_NodePointer id; /* the id of the node at this depth */
+ UA_UInt16 depth;
+};
+
+static UA_Boolean
+isNodeInTreeNoCircular(UA_Server *server,
+ UA_NodePointer leafNode,
+ UA_NodePointer nodeToFind,
+ struct ref_history *visitedRefs,
+ const UA_ReferenceTypeSet *relevantRefs) {
+ if(UA_NodePointer_equal(nodeToFind, leafNode))
+ return true;
+
+ if(visitedRefs->depth >= UA_MAX_TREE_RECURSE)
+ return false;
+
+ const UA_Node *node = UA_NODESTORE_GETFROMREF(server, leafNode);
+ if(!node)
+ return false;
+
+ for(size_t i = 0; i < node->head.referencesSize; ++i) {
+ UA_NodeReferenceKind *rk = &node->head.references[i];
+ /* Search upwards in the tree */
+ if(!rk->isInverse)
+ continue;
+
+ /* Consider only the indicated reference types */
+ if(!UA_ReferenceTypeSet_contains(relevantRefs, rk->referenceTypeIndex))
+ continue;
+
+ /* Match the targets or recurse */
+ const UA_ReferenceTarget *t = NULL;
+ while((t = UA_NodeReferenceKind_iterate(rk, t))) {
+ /* Don't follow remote targets */
+ if(!UA_NodePointer_isLocal(t->targetId))
+ continue;
+
+ /* Check if we already have seen the referenced node and skip to
+ * avoid endless recursion. Do this only at every 5th depth to save
+ * effort. Circular dependencies are rare and forbidden for most
+ * reference types. */
+ if(visitedRefs->depth % 5 == 4) {
+ struct ref_history *last = visitedRefs;
+ UA_Boolean skip = false;
+ while(last) {
+ if(UA_NodePointer_equal(last->id, t->targetId)) {
+ skip = true;
+ break;
+ }
+ last = last->parent;
+ }
+ if(skip)
+ continue;
+ }
+
+ /* Stack-allocate the visitedRefs structure for the next depth */
+ struct ref_history nextVisitedRefs = {visitedRefs, t->targetId,
+ (UA_UInt16)(visitedRefs->depth+1)};
+
+ /* Recurse */
+ UA_Boolean foundRecursive =
+ isNodeInTreeNoCircular(server, t->targetId, nodeToFind,
+ &nextVisitedRefs, relevantRefs);
+ if(foundRecursive) {
+ UA_NODESTORE_RELEASE(server, node);
+ return true;
+ }
+ }
+ }
+
+ UA_NODESTORE_RELEASE(server, node);
+ return false;
+}
+
+UA_Boolean
+isNodeInTree(UA_Server *server, const UA_NodeId *leafNode,
+ const UA_NodeId *nodeToFind,
+ const UA_ReferenceTypeSet *relevantRefs) {
+ UA_NodePointer leafP = UA_NodePointer_fromNodeId(leafNode);
+ UA_NodePointer targetP = UA_NodePointer_fromNodeId(nodeToFind);
+ struct ref_history visitedRefs = {NULL, leafP, 0};
+ return isNodeInTreeNoCircular(server, leafP, targetP,
+ &visitedRefs, relevantRefs);
+}
+
+UA_Boolean
+isNodeInTree_singleRef(UA_Server *server, const UA_NodeId *leafNode,
+ const UA_NodeId *nodeToFind, const UA_Byte relevantRefTypeIndex) {
+ UA_ReferenceTypeSet reftypes = UA_REFTYPESET(relevantRefTypeIndex);
+ return isNodeInTree(server, leafNode, nodeToFind, &reftypes);
+}
static enum ZIP_CMP
cmpTarget(const void *a, const void *b) {
@@ -32437,32 +35031,22 @@ cmpTarget(const void *a, const void *b) {
return (enum ZIP_CMP)UA_ExpandedNodeId_order(aa->target, bb->target);
}
-ZIP_HEAD(RefHead, RefEntry);
-typedef struct RefHead RefHead;
-ZIP_PROTTYPE(RefHead, RefEntry, RefEntry)
-ZIP_IMPL(RefHead, RefEntry, zipfields, RefEntry, zipfields, cmpTarget)
+ZIP_FUNCTIONS(RefHead, RefEntry, zipfields, RefEntry, zipfields, cmpTarget)
-typedef struct {
- UA_ExpandedNodeId *targets;
- RefHead head;
- size_t capacity; /* available space */
- size_t size; /* used space */
-} RefTree;
-
-static UA_StatusCode UA_FUNC_ATTR_WARN_UNUSED_RESULT
+UA_StatusCode
RefTree_init(RefTree *rt) {
rt->size = 0;
rt->capacity = 0;
ZIP_INIT(&rt->head);
- size_t space = (sizeof(UA_ExpandedNodeId) + sizeof(RefEntry)) * UA_BROWSE_INITIAL_SIZE;
+ size_t space = (sizeof(UA_ExpandedNodeId) + sizeof(RefEntry)) * UA_REFTREE_INITIAL_SIZE;
rt->targets = (UA_ExpandedNodeId*)UA_malloc(space);
if(!rt->targets)
return UA_STATUSCODE_BADOUTOFMEMORY;
- rt->capacity = UA_BROWSE_INITIAL_SIZE;
+ rt->capacity = UA_REFTREE_INITIAL_SIZE;
return UA_STATUSCODE_GOOD;
}
-static void
+void
RefTree_clear(RefTree *rt) {
for(size_t i = 0; i < rt->size; i++)
UA_ExpandedNodeId_clear(&rt->targets[i]);
@@ -32481,6 +35065,9 @@ RefTree_double(RefTree *rt) {
return UA_STATUSCODE_BADOUTOFMEMORY;
/* Repair the pointers for the realloced array+tree */
+ // What is this sorcery?
+ // FIXME: This needs some cleaning up or explanation.
+ // IMO uintptr could be completely avoided here.
uintptr_t arraydiff = (uintptr_t)newTargets - (uintptr_t)rt->targets;
RefEntry *reArray = (RefEntry*)
((uintptr_t)newTargets + (capacity * sizeof(UA_ExpandedNodeId)));
@@ -32499,20 +35086,26 @@ RefTree_double(RefTree *rt) {
reArray[i].target = (UA_ExpandedNodeId*)((uintptr_t)reArray[i].target + arraydiff);
}
- rt->head.zip_root = (RefEntry*)((uintptr_t)rt->head.zip_root + entrydiff);
+ ZIP_ROOT(&rt->head) = (RefEntry*)((uintptr_t)ZIP_ROOT(&rt->head) + entrydiff);
rt->capacity = capacity;
rt->targets = newTargets;
return UA_STATUSCODE_GOOD;
}
-static UA_StatusCode UA_FUNC_ATTR_WARN_UNUSED_RESULT
-RefTree_add(RefTree *rt, const UA_ExpandedNodeId *target) {
+static UA_StatusCode
+RefTree_add(RefTree *rt, UA_NodePointer target, UA_Boolean *duplicate) {
+ UA_ExpandedNodeId en = UA_NodePointer_toExpandedNodeId(target);
+
/* Is the target already in the tree? */
RefEntry dummy;
- dummy.target = target;
- dummy.targetHash = UA_ExpandedNodeId_hash(target);
- if(ZIP_FIND(RefHead, &rt->head, &dummy))
+ memset(&dummy, 0, sizeof(RefEntry));
+ dummy.target = &en;
+ dummy.targetHash = UA_ExpandedNodeId_hash(&en);
+ if(ZIP_FIND(RefHead, &rt->head, &dummy)) {
+ if(duplicate)
+ *duplicate = true;
return UA_STATUSCODE_GOOD;
+ }
UA_StatusCode s = UA_STATUSCODE_GOOD;
if(rt->capacity <= rt->size) {
@@ -32520,7 +35113,7 @@ RefTree_add(RefTree *rt, const UA_ExpandedNodeId *target) {
if(s != UA_STATUSCODE_GOOD)
return s;
}
- s = UA_ExpandedNodeId_copy(target, &rt->targets[rt->size]);
+ s = UA_ExpandedNodeId_copy(&en, &rt->targets[rt->size]);
if(s != UA_STATUSCODE_GOOD)
return s;
RefEntry *re = (RefEntry*)((uintptr_t)rt->targets +
@@ -32528,34 +35121,65 @@ RefTree_add(RefTree *rt, const UA_ExpandedNodeId *target) {
(sizeof(RefEntry) * rt->size));
re->target = &rt->targets[rt->size];
re->targetHash = dummy.targetHash;
- ZIP_INSERT(RefHead, &rt->head, re, ZIP_FFS32(UA_UInt32_random()));
+ ZIP_INSERT(RefHead, &rt->head, re, UA_UInt32_random());
rt->size++;
return UA_STATUSCODE_GOOD;
}
-static UA_Boolean
-relevantReference(const UA_NodeId *refType, size_t relevantRefsSize,
- const UA_NodeId *relevantRefs) {
- if(!relevantRefs)
- return true;
- for(size_t i = 0; i < relevantRefsSize; i++) {
- if(UA_NodeId_equal(refType, &relevantRefs[i]))
- return true;
- }
- return false;
+UA_StatusCode
+RefTree_addNodeId(RefTree *rt, const UA_NodeId *target,
+ UA_Boolean *duplicate) {
+ return RefTree_add(rt, UA_NodePointer_fromNodeId(target), duplicate);
+}
+
+UA_Boolean
+RefTree_contains(RefTree *rt, const UA_ExpandedNodeId *target) {
+ RefEntry dummy;
+ dummy.target = target;
+ dummy.targetHash = UA_ExpandedNodeId_hash(target);
+ return !!ZIP_FIND(RefHead, &rt->head, &dummy);
+}
+
+UA_Boolean
+RefTree_containsNodeId(RefTree *rt, const UA_NodeId *target) {
+ UA_ExpandedNodeId en;
+ en.nodeId = *target;
+ en.namespaceUri = UA_STRING_NULL;
+ en.serverIndex = 0;
+ return RefTree_contains(rt, &en);
}
+/********************/
+/* Browse Recursive */
+/********************/
+
static UA_StatusCode
-addRelevantReferences(UA_Server *server, RefTree *rt, const UA_NodeId *nodeId,
- size_t refTypesSize, const UA_NodeId *refTypes,
- UA_BrowseDirection browseDirection) {
- const UA_Node *node = UA_NODESTORE_GET(server, nodeId);
+browseRecursiveInner(UA_Server *server, RefTree *rt, UA_UInt16 depth, UA_Boolean skip,
+ UA_NodePointer nodeP, UA_BrowseDirection browseDirection,
+ const UA_ReferenceTypeSet *refTypes, UA_UInt32 nodeClassMask) {
+ /* Have we reached the max recursion depth? */
+ if(depth >= UA_MAX_TREE_RECURSE)
+ return UA_STATUSCODE_GOOD;
+
+ const UA_Node *node = UA_NODESTORE_GETFROMREF(server, nodeP);
if(!node)
return UA_STATUSCODE_BADNODEIDUNKNOWN;
UA_StatusCode retval = UA_STATUSCODE_GOOD;
- for(size_t i = 0; i < node->referencesSize; i++) {
- UA_NodeReferenceKind *rk = &node->references[i];
+ const UA_NodeHead *head = &node->head;
+
+ /* Add the current node to the results if we don't want to skip it (i.e. for
+ * includeStartNodes) and it matches the nodeClassMask filter. Process the
+ * children also if the nodeClassMask does not match. */
+ if(!skip && matchClassMask(node, nodeClassMask)) {
+ UA_Boolean duplicate = false;
+ retval = RefTree_addNodeId(rt, &head->nodeId, &duplicate);
+ if(duplicate || retval != UA_STATUSCODE_GOOD)
+ goto cleanup;
+ }
+
+ for(size_t i = 0; i < head->referencesSize; i++) {
+ UA_NodeReferenceKind *rk = &head->references[i];
/* Reference in the right direction? */
if(rk->isInverse && browseDirection == UA_BROWSEDIRECTION_FORWARD)
@@ -32564,11 +35188,18 @@ addRelevantReferences(UA_Server *server, RefTree *rt, const UA_NodeId *nodeId,
continue;
/* Is the reference part of the hierarchy of references we look for? */
- if(!relevantReference(&rk->referenceTypeId, refTypesSize, refTypes))
+ if(!UA_ReferenceTypeSet_contains(refTypes, rk->referenceTypeIndex))
continue;
- for(size_t k = 0; k < rk->refTargetsSize; k++) {
- retval = RefTree_add(rt, &rk->refTargets[k].targetId);
+ const UA_ReferenceTarget *target = NULL;
+ while((target = UA_NodeReferenceKind_iterate(rk, target))) {
+ if(UA_NodePointer_isLocal(target->targetId)) {
+ retval = browseRecursiveInner(server, rt, (UA_UInt16)(depth+1), false,
+ target->targetId, browseDirection,
+ refTypes, nodeClassMask);
+ } else {
+ retval = RefTree_add(rt, target->targetId, NULL);
+ }
if(retval != UA_STATUSCODE_GOOD)
goto cleanup;
}
@@ -32580,133 +35211,63 @@ addRelevantReferences(UA_Server *server, RefTree *rt, const UA_NodeId *nodeId,
}
UA_StatusCode
-browseRecursive(UA_Server *server,
- size_t startNodesSize, const UA_NodeId *startNodes,
- size_t refTypesSize, const UA_NodeId *refTypes,
- UA_BrowseDirection browseDirection, UA_Boolean includeStartNodes,
+browseRecursive(UA_Server *server, size_t startNodesSize, const UA_NodeId *startNodes,
+ UA_BrowseDirection browseDirection, const UA_ReferenceTypeSet *refTypes,
+ UA_UInt32 nodeClassMask, UA_Boolean includeStartNodes,
size_t *resultsSize, UA_ExpandedNodeId **results) {
RefTree rt;
UA_StatusCode retval = RefTree_init(&rt);
if(retval != UA_STATUSCODE_GOOD)
return retval;
- /* Add the start nodes? */
- UA_ExpandedNodeId en = UA_EXPANDEDNODEID_NULL;
- for(size_t i = 0; i < startNodesSize && retval == UA_STATUSCODE_GOOD; i++) {
- if(includeStartNodes) {
- en.nodeId = startNodes[i];
- retval = RefTree_add(&rt, &en);
- } else {
- retval = addRelevantReferences(server, &rt, &startNodes[i],
- refTypesSize, refTypes, browseDirection);
- }
- }
- if(retval != UA_STATUSCODE_GOOD) {
- RefTree_clear(&rt);
- return retval;
- }
-
- /* Loop over the targets we have so far. This recurses, as new targets are
- * added to rt. */
- for(size_t i = 0; i < rt.size; i++) {
- /* Dont recurse into remote nodes */
- if(rt.targets[i].serverIndex > 0)
- continue;
- if(rt.targets[i].namespaceUri.data != NULL)
- continue;
-
- retval = addRelevantReferences(server, &rt, &rt.targets[i].nodeId,
- refTypesSize, refTypes, browseDirection);
- if(retval != UA_STATUSCODE_GOOD) {
- RefTree_clear(&rt);
- return retval;
- }
+ for(size_t i = 0; i < startNodesSize; i++) {
+ /* Call the inner recursive browse separately for the search direction.
+ * Otherwise we might take one step up and another step down in the
+ * search tree. */
+ if(browseDirection == UA_BROWSEDIRECTION_FORWARD ||
+ browseDirection == UA_BROWSEDIRECTION_BOTH)
+ retval |= browseRecursiveInner(server, &rt, 0, !includeStartNodes,
+ UA_NodePointer_fromNodeId(&startNodes[i]),
+ UA_BROWSEDIRECTION_FORWARD,
+ refTypes, nodeClassMask);
+ if(browseDirection == UA_BROWSEDIRECTION_INVERSE ||
+ browseDirection == UA_BROWSEDIRECTION_BOTH)
+ retval |= browseRecursiveInner(server, &rt, 0, !includeStartNodes,
+ UA_NodePointer_fromNodeId(&startNodes[i]),
+ UA_BROWSEDIRECTION_INVERSE,
+ refTypes, nodeClassMask);
+ if(retval != UA_STATUSCODE_GOOD)
+ break;
}
- if(rt.size > 0) {
+ if(rt.size > 0 && retval == UA_STATUSCODE_GOOD) {
*results = rt.targets;
*resultsSize = rt.size;
} else {
RefTree_clear(&rt);
}
-
- return UA_STATUSCODE_GOOD;
-}
-
-/* Only if IncludeSubtypes is selected */
-UA_StatusCode
-referenceSubtypes(UA_Server *server, const UA_NodeId *refType,
- size_t *refTypesSize, UA_NodeId **refTypes) {
- /* Leave refTypes == NULL */
- if(UA_NodeId_isNull(refType))
- return UA_STATUSCODE_GOOD;
-
- /* Browse recursive for the hierarchy of sub-references */
- UA_ExpandedNodeId *rt = NULL;
- size_t rtSize = 0;
- UA_NodeId hasSubtype = UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE);
- UA_StatusCode retval = browseRecursive(server, 1, refType, 1, &hasSubtype,
- UA_BROWSEDIRECTION_FORWARD, true, &rtSize, &rt);
- if(retval != UA_STATUSCODE_GOOD)
- return retval;
-
- UA_assert(rtSize > 0);
-
- /* Allocate space (realloc if non-NULL) */
- UA_NodeId *newRt = NULL;
- if(!*refTypes) {
- newRt = (UA_NodeId*)UA_malloc(rtSize * UA_TYPES[UA_TYPES_NODEID].memSize);
- } else {
- newRt = (UA_NodeId*)UA_realloc(*refTypes, (*refTypesSize + rtSize) *
- UA_TYPES[UA_TYPES_NODEID].memSize);
- }
- if(!newRt) {
- UA_Array_delete(rt, rtSize, &UA_TYPES[UA_TYPES_EXPANDEDNODEID]);
- return UA_STATUSCODE_BADOUTOFMEMORY;
- }
- *refTypes = newRt;
-
- /* Move NodeIds */
- for(size_t i = 0; i < rtSize; i++) {
- (*refTypes)[*refTypesSize + i] = rt[i].nodeId;
- UA_NodeId_init(&rt[i].nodeId);
- }
- *refTypesSize += rtSize;
- UA_Array_delete(rt, rtSize, &UA_TYPES[UA_TYPES_EXPANDEDNODEID]);
- return UA_STATUSCODE_GOOD;
+ return retval;
}
UA_StatusCode
UA_Server_browseRecursive(UA_Server *server, const UA_BrowseDescription *bd,
size_t *resultsSize, UA_ExpandedNodeId **results) {
+ UA_LOCK(&server->serviceMutex);
+
/* Set the list of relevant reference types */
- UA_LOCK(server->serviceMutex);
- UA_NodeId *refTypes = NULL;
- size_t refTypesSize = 0;
- UA_StatusCode retval = UA_STATUSCODE_GOOD;
- if(!UA_NodeId_isNull(&bd->referenceTypeId)) {
- if(!bd->includeSubtypes) {
- refTypes = (UA_NodeId*)(uintptr_t)&bd->referenceTypeId;
- refTypesSize = 1;
- } else {
- retval = referenceSubtypes(server, &bd->referenceTypeId,
- &refTypesSize, &refTypes);
- if(retval != UA_STATUSCODE_GOOD) {
- UA_UNLOCK(server->serviceMutex);
- return retval;
- }
- }
+ UA_ReferenceTypeSet refTypes;
+ UA_StatusCode retval = referenceTypeIndices(server, &bd->referenceTypeId,
+ &refTypes, bd->includeSubtypes);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_UNLOCK(&server->serviceMutex);
+ return retval;
}
/* Browse */
- retval = browseRecursive(server, 1, &bd->nodeId, refTypesSize, refTypes,
- bd->browseDirection, false, resultsSize, results);
+ retval = browseRecursive(server, 1, &bd->nodeId, bd->browseDirection,
+ &refTypes, bd->nodeClassMask, false, resultsSize, results);
- /* Clean up */
- if(refTypes && bd->includeSubtypes)
- UA_Array_delete(refTypes, refTypesSize, &UA_TYPES[UA_TYPES_NODEID]);
-
- UA_UNLOCK(server->serviceMutex);
+ UA_UNLOCK(&server->serviceMutex);
return retval;
}
@@ -32724,10 +35285,10 @@ static UA_StatusCode UA_FUNC_ATTR_WARN_UNUSED_RESULT
RefResult_init(RefResult *rr) {
memset(rr, 0, sizeof(RefResult));
rr->descr = (UA_ReferenceDescription*)
- UA_Array_new(UA_BROWSE_INITIAL_SIZE, &UA_TYPES[UA_TYPES_REFERENCEDESCRIPTION]);
+ UA_Array_new(UA_REFTREE_INITIAL_SIZE, &UA_TYPES[UA_TYPES_REFERENCEDESCRIPTION]);
if(!rr->descr)
return UA_STATUSCODE_BADOUTOFMEMORY;
- rr->capacity = UA_BROWSE_INITIAL_SIZE;
+ rr->capacity = UA_REFTREE_INITIAL_SIZE;
rr->size = 0;
return UA_STATUSCODE_GOOD;
}
@@ -32756,30 +35317,30 @@ RefResult_clear(RefResult *rr) {
struct ContinuationPoint {
ContinuationPoint *next;
UA_ByteString identifier;
+
+ /* Parameters of the Browse Request */
UA_BrowseDescription browseDescription;
UA_UInt32 maxReferences;
+ UA_ReferenceTypeSet relevantReferences;
- size_t relevantReferencesSize;
- UA_NodeId *relevantReferences;
-
- /* The last point in the node references? */
- size_t referenceKindIndex;
- size_t targetIndex;
+ /* The next target to be transmitted to the client */
+ UA_ExpandedNodeId nextTarget;
+ UA_Byte nextRefKindIndex;
};
ContinuationPoint *
ContinuationPoint_clear(ContinuationPoint *cp) {
UA_ByteString_clear(&cp->identifier);
UA_BrowseDescription_clear(&cp->browseDescription);
- UA_Array_delete(cp->relevantReferences, cp->relevantReferencesSize,
- &UA_TYPES[UA_TYPES_NODEID]);
+ UA_ExpandedNodeId_clear(&cp->nextTarget);
return cp->next;
}
/* Target node on top of the stack */
static UA_StatusCode UA_FUNC_ATTR_WARN_UNUSED_RESULT
-addReferenceDescription(UA_Server *server, RefResult *rr, const UA_NodeReferenceKind *ref,
- UA_UInt32 mask, const UA_ExpandedNodeId *nodeId, const UA_Node *curr) {
+addReferenceDescription(UA_Server *server, RefResult *rr,
+ const UA_NodeReferenceKind *ref, UA_UInt32 mask,
+ UA_NodePointer nodeP, const UA_Node *curr) {
/* Ensure capacity is left */
UA_StatusCode retval = UA_STATUSCODE_GOOD;
if(rr->size >= rr->capacity) {
@@ -32791,9 +35352,13 @@ addReferenceDescription(UA_Server *server, RefResult *rr, const UA_NodeReference
UA_ReferenceDescription *descr = &rr->descr[rr->size];
/* Fields without access to the actual node */
- retval = UA_ExpandedNodeId_copy(nodeId, &descr->nodeId);
- if(mask & UA_BROWSERESULTMASK_REFERENCETYPEID)
- retval |= UA_NodeId_copy(&ref->referenceTypeId, &descr->referenceTypeId);
+ UA_ExpandedNodeId en = UA_NodePointer_toExpandedNodeId(nodeP);
+ retval = UA_ExpandedNodeId_copy(&en, &descr->nodeId);
+ if(mask & UA_BROWSERESULTMASK_REFERENCETYPEID) {
+ const UA_NodeId *refTypeId =
+ UA_NODESTORE_GETREFERENCETYPEID(server, ref->referenceTypeIndex);
+ retval |= UA_NodeId_copy(refTypeId, &descr->referenceTypeId);
+ }
if(mask & UA_BROWSERESULTMASK_ISFORWARD)
descr->isForward = !ref->isInverse;
@@ -32805,17 +35370,17 @@ addReferenceDescription(UA_Server *server, RefResult *rr, const UA_NodeReference
/* Fields that require the actual node */
if(mask & UA_BROWSERESULTMASK_NODECLASS)
- retval |= UA_NodeClass_copy(&curr->nodeClass, &descr->nodeClass);
+ descr->nodeClass = curr->head.nodeClass;
if(mask & UA_BROWSERESULTMASK_BROWSENAME)
- retval |= UA_QualifiedName_copy(&curr->browseName, &descr->browseName);
+ retval |= UA_QualifiedName_copy(&curr->head.browseName, &descr->browseName);
if(mask & UA_BROWSERESULTMASK_DISPLAYNAME)
- retval |= UA_LocalizedText_copy(&curr->displayName, &descr->displayName);
+ retval |= UA_LocalizedText_copy(&curr->head.displayName, &descr->displayName);
if(mask & UA_BROWSERESULTMASK_TYPEDEFINITION) {
- if(curr->nodeClass == UA_NODECLASS_OBJECT ||
- curr->nodeClass == UA_NODECLASS_VARIABLE) {
- const UA_Node *type = getNodeType(server, curr);
+ if(curr->head.nodeClass == UA_NODECLASS_OBJECT ||
+ curr->head.nodeClass == UA_NODECLASS_VARIABLE) {
+ const UA_Node *type = getNodeType(server, &curr->head);
if(type) {
- retval |= UA_NodeId_copy(&type->nodeId, &descr->typeDefinition.nodeId);
+ retval |= UA_NodeId_copy(&type->head.nodeId, &descr->typeDefinition.nodeId);
UA_NODESTORE_RELEASE(server, type);
}
}
@@ -32828,29 +35393,51 @@ addReferenceDescription(UA_Server *server, RefResult *rr, const UA_NodeReference
return retval;
}
-static UA_Boolean
-matchClassMask(const UA_Node *node, UA_UInt32 nodeClassMask) {
- if(nodeClassMask != UA_NODECLASS_UNSPECIFIED &&
- (node->nodeClass & nodeClassMask) == 0)
- return false;
- return true;
-}
-
/* Returns whether the node / continuationpoint is done */
static UA_StatusCode
-browseReferences(UA_Server *server, const UA_Node *node,
+browseReferences(UA_Server *server, const UA_NodeHead *head,
ContinuationPoint *cp, RefResult *rr, UA_Boolean *done) {
- UA_assert(cp != NULL);
- const UA_BrowseDescription *bd= &cp->browseDescription;
+ UA_assert(cp);
+ const UA_BrowseDescription *bd = &cp->browseDescription;
- size_t referenceKindIndex = cp->referenceKindIndex;
- size_t targetIndex = cp->targetIndex;
+ size_t i = 0;
+ const UA_ReferenceTarget *ref = NULL;
+
+ /* If the cp was previously used, skip forward to the next ReferenceType to
+ * be transmitted. */
+ if(cp->identifier.length > 0) {
+ for(; i < head->referencesSize; ++i) {
+ UA_NodeReferenceKind *rk = &head->references[i];
+
+ /* Was this the last transmitted ReferenceType? */
+ if(head->references[i].referenceTypeIndex != cp->nextRefKindIndex)
+ continue;
- /* Loop over the node's references */
- const UA_Node *target = NULL;
+ /* Reference in the right direction? */
+ if(rk->isInverse && bd->browseDirection == UA_BROWSEDIRECTION_FORWARD)
+ continue;
+ if(!rk->isInverse && bd->browseDirection == UA_BROWSEDIRECTION_INVERSE)
+ continue;
+
+ /* Get the next target */
+ ref = UA_NodeReferenceKind_findTarget(rk, &cp->nextTarget);
+ if(ref)
+ break;
+
+ /* The target no longer exists for this ReferenceType (and
+ * direction). Continue to iterate for the case that a nodestore has
+ * a duplicate UA_NodeReferenceKind (should not happen though). */
+ }
+
+ /* Fail with an error if the reference no longer exists. */
+ if(!ref)
+ return UA_STATUSCODE_BADINTERNALERROR;
+ }
+
+ /* Loop over the ReferenceTypes */
UA_StatusCode retval = UA_STATUSCODE_GOOD;
- for(; referenceKindIndex < node->referencesSize; ++referenceKindIndex) {
- UA_NodeReferenceKind *rk = &node->references[referenceKindIndex];
+ for(; i < head->referencesSize; ++i) {
+ UA_NodeReferenceKind *rk = &head->references[i];
/* Reference in the right direction? */
if(rk->isInverse && bd->browseDirection == UA_BROWSEDIRECTION_FORWARD)
@@ -32859,46 +35446,48 @@ browseReferences(UA_Server *server, const UA_Node *node,
continue;
/* Is the reference part of the hierarchy of references we look for? */
- if(!relevantReference(&rk->referenceTypeId, cp->relevantReferencesSize,
- cp->relevantReferences))
+ if(!UA_ReferenceTypeSet_contains(&cp->relevantReferences,
+ rk->referenceTypeIndex))
continue;
- /* Loop over the targets */
- for(; targetIndex < rk->refTargetsSize; ++targetIndex) {
- target = NULL;
+ /* We have a matching ReferenceType! */
+ /* Loop over the targets for the ReferenceType. Start with the first
+ * entry if we don't have a known entry-point from the cp. */
+ if(!ref)
+ ref = UA_NodeReferenceKind_iterate(rk, ref);
+ for(;ref; ref = UA_NodeReferenceKind_iterate(rk, ref)) {
/* Get the node if it is not a remote reference */
- if(rk->refTargets[targetIndex].targetId.serverIndex == 0 &&
- rk->refTargets[targetIndex].targetId.namespaceUri.data == NULL) {
- target = UA_NODESTORE_GET(server,
- &rk->refTargets[targetIndex].targetId.nodeId);
-
- /* Test if the node class matches */
- if(target && !matchClassMask(target, bd->nodeClassMask)) {
- if(target)
- UA_NODESTORE_RELEASE(server, target);
- continue;
- }
+ const UA_Node *target =
+ UA_NODESTORE_GETFROMREF(server, ref->targetId);
+
+ /* Test if the node class matches */
+ if(target && !matchClassMask(target, bd->nodeClassMask)) {
+ UA_NODESTORE_RELEASE(server, target);
+ continue;
}
- /* A match! Did we reach maxrefs? */
+ /* We have a matching target! */
+
+ /* Reached maxrefs. Update the cp and bail. */
if(rr->size >= cp->maxReferences) {
- cp->referenceKindIndex = referenceKindIndex;
- cp->targetIndex = targetIndex;
if(target)
UA_NODESTORE_RELEASE(server, target);
- return UA_STATUSCODE_GOOD;
+ cp->nextRefKindIndex = rk->referenceTypeIndex;
+ /* Make a deep copy */
+ UA_ExpandedNodeId tmpEn =
+ UA_NodePointer_toExpandedNodeId(ref->targetId);
+ return UA_ExpandedNodeId_copy(&tmpEn, &cp->nextTarget);
}
/* Copy the node description. Target is on top of the stack */
retval = addReferenceDescription(server, rr, rk, bd->resultMask,
- &rk->refTargets[targetIndex].targetId, target);
- UA_NODESTORE_RELEASE(server, target);
+ ref->targetId, target);
+ if(target)
+ UA_NODESTORE_RELEASE(server, target);
if(retval != UA_STATUSCODE_GOOD)
return retval;
}
-
- targetIndex = 0; /* Start at index 0 for the next reference kind */
}
/* The node is done */
@@ -32913,6 +35502,7 @@ browseReferences(UA_Server *server, const UA_Node *node,
static UA_Boolean
browseWithContinuation(UA_Server *server, UA_Session *session,
ContinuationPoint *cp, UA_BrowseResult *result) {
+ UA_assert(cp);
const UA_BrowseDescription *descr = &cp->browseDescription;
/* Is the browsedirection valid? */
@@ -32931,7 +35521,7 @@ browseWithContinuation(UA_Server *server, UA_Session *session,
return true;
}
- UA_Boolean isRef = (reftype->nodeClass == UA_NODECLASS_REFERENCETYPE);
+ UA_Boolean isRef = (reftype->head.nodeClass == UA_NODECLASS_REFERENCETYPE);
UA_NODESTORE_RELEASE(server, reftype);
if(!isRef) {
@@ -32947,9 +35537,10 @@ browseWithContinuation(UA_Server *server, UA_Session *session,
}
if(session != &server->adminSession &&
- !server->config.accessControl.allowBrowseNode(server, &server->config.accessControl,
- &session->sessionId, session->sessionHandle,
- &descr->nodeId, node->context)) {
+ !server->config.accessControl.
+ allowBrowseNode(server, &server->config.accessControl,
+ &session->sessionId, session->sessionHandle,
+ &descr->nodeId, node->head.context)) {
result->statusCode = UA_STATUSCODE_BADUSERACCESSDENIED;
UA_NODESTORE_RELEASE(server, node);
return true;
@@ -32964,7 +35555,7 @@ browseWithContinuation(UA_Server *server, UA_Session *session,
/* Browse the references */
UA_Boolean done = false;
- result->statusCode = browseReferences(server, node, cp, &rr, &done);
+ result->statusCode = browseReferences(server, &node->head, cp, &rr, &done);
UA_NODESTORE_RELEASE(server, node);
if(result->statusCode != UA_STATUSCODE_GOOD) {
RefResult_clear(&rr);
@@ -32989,48 +35580,37 @@ void
Operation_Browse(UA_Server *server, UA_Session *session, const UA_UInt32 *maxrefs,
const UA_BrowseDescription *descr, UA_BrowseResult *result) {
/* Stack-allocate a temporary cp */
- UA_STACKARRAY(ContinuationPoint, cp, 1);
- memset(cp, 0, sizeof(ContinuationPoint));
- cp->maxReferences = *maxrefs;
- cp->browseDescription = *descr; /* Shallow copy. Deep-copy later if we persist the cp. */
+ ContinuationPoint cp;
+ memset(&cp, 0, sizeof(ContinuationPoint));
+ cp.maxReferences = *maxrefs;
+ cp.browseDescription = *descr; /* Shallow copy. Deep-copy later if we persist the cp. */
/* How many references can we return at most? */
- if(cp->maxReferences == 0) {
+ if(cp.maxReferences == 0) {
if(server->config.maxReferencesPerNode != 0) {
- cp->maxReferences = server->config.maxReferencesPerNode;
+ cp.maxReferences = server->config.maxReferencesPerNode;
} else {
- cp->maxReferences = UA_INT32_MAX;
+ cp.maxReferences = UA_INT32_MAX;
}
} else {
if(server->config.maxReferencesPerNode != 0 &&
- cp->maxReferences > server->config.maxReferencesPerNode) {
- cp->maxReferences= server->config.maxReferencesPerNode;
+ cp.maxReferences > server->config.maxReferencesPerNode) {
+ cp.maxReferences= server->config.maxReferencesPerNode;
}
}
/* Get the list of relevant reference types */
- if(!UA_NodeId_isNull(&descr->referenceTypeId)) {
- if(!descr->includeSubtypes) {
- cp->relevantReferences = (UA_NodeId*)(uintptr_t)&descr->referenceTypeId;
- cp->relevantReferencesSize = 1;
- } else {
- result->statusCode =
- referenceSubtypes(server, &descr->referenceTypeId,
- &cp->relevantReferencesSize, &cp->relevantReferences);
- if(result->statusCode != UA_STATUSCODE_GOOD)
- return;
- }
- }
+ result->statusCode =
+ referenceTypeIndices(server, &descr->referenceTypeId,
+ &cp.relevantReferences, descr->includeSubtypes);
+ if(result->statusCode != UA_STATUSCODE_GOOD)
+ return;
- UA_Boolean done = browseWithContinuation(server, session, cp, result);
+ UA_Boolean done = browseWithContinuation(server, session, &cp, result);
/* Exit early if done or an error occurred */
- if(done || result->statusCode != UA_STATUSCODE_GOOD) {
- if(descr->includeSubtypes)
- UA_Array_delete(cp->relevantReferences, cp->relevantReferencesSize,
- &UA_TYPES[UA_TYPES_NODEID]);
+ if(done || result->statusCode != UA_STATUSCODE_GOOD)
return;
- }
/* Persist the new continuation point */
@@ -33039,7 +35619,7 @@ Operation_Browse(UA_Server *server, UA_Session *session, const UA_UInt32 *maxref
UA_StatusCode retval = UA_STATUSCODE_GOOD;
/* Enough space for the continuation point? */
- if(session->availableContinuationPoints <= 0) {
+ if(session->availableContinuationPoints == 0) {
retval = UA_STATUSCODE_BADNOCONTINUATIONPOINTS;
goto cleanup;
}
@@ -33050,26 +35630,16 @@ Operation_Browse(UA_Server *server, UA_Session *session, const UA_UInt32 *maxref
retval = UA_STATUSCODE_BADOUTOFMEMORY;
goto cleanup;
}
- memset(cp2, 0, sizeof(ContinuationPoint));
- cp2->referenceKindIndex = cp->referenceKindIndex;
- cp2->targetIndex = cp->targetIndex;
- cp2->maxReferences = cp->maxReferences;
- if(descr->includeSubtypes) {
- cp2->relevantReferences = cp->relevantReferences;
- cp2->relevantReferencesSize = cp->relevantReferencesSize;
- } else {
- retval = UA_Array_copy(cp->relevantReferences, cp->relevantReferencesSize,
- (void**)&cp2->relevantReferences, &UA_TYPES[UA_TYPES_NODEID]);
- if(retval != UA_STATUSCODE_GOOD)
- goto cleanup;
- cp2->relevantReferencesSize = cp->relevantReferencesSize;
- }
-
- /* Copy the description */
+ memset(cp2, 0, sizeof(ContinuationPoint));
+ /* The BrowseDescription is only a shallow copy in cp */
retval = UA_BrowseDescription_copy(descr, &cp2->browseDescription);
if(retval != UA_STATUSCODE_GOOD)
goto cleanup;
+ cp2->maxReferences = cp.maxReferences;
+ cp2->relevantReferences = cp.relevantReferences;
+ cp2->nextTarget = cp.nextTarget;
+ cp2->nextRefKindIndex = cp.nextRefKindIndex;
/* Create a random bytestring via a Guid */
ident = UA_Guid_new();
@@ -33104,7 +35674,7 @@ Operation_Browse(UA_Server *server, UA_Session *session, const UA_UInt32 *maxref
void Service_Browse(UA_Server *server, UA_Session *session,
const UA_BrowseRequest *request, UA_BrowseResponse *response) {
UA_LOG_DEBUG_SESSION(&server->config.logger, session, "Processing BrowseRequest");
- UA_LOCK_ASSERT(server->serviceMutex, 1);
+ UA_LOCK_ASSERT(&server->serviceMutex, 1);
/* Test the number of operations in the request */
if(server->config.maxNodesPerBrowse != 0 &&
@@ -33120,10 +35690,13 @@ void Service_Browse(UA_Server *server, UA_Session *session,
}
response->responseHeader.serviceResult =
- UA_Server_processServiceOperations(server, session, (UA_ServiceOperation)Operation_Browse,
+ UA_Server_processServiceOperations(server, session,
+ (UA_ServiceOperation)Operation_Browse,
&request->requestedMaxReferencesPerNode,
- &request->nodesToBrowseSize, &UA_TYPES[UA_TYPES_BROWSEDESCRIPTION],
- &response->resultsSize, &UA_TYPES[UA_TYPES_BROWSERESULT]);
+ &request->nodesToBrowseSize,
+ &UA_TYPES[UA_TYPES_BROWSEDESCRIPTION],
+ &response->resultsSize,
+ &UA_TYPES[UA_TYPES_BROWSERESULT]);
}
UA_BrowseResult
@@ -33131,9 +35704,9 @@ UA_Server_browse(UA_Server *server, UA_UInt32 maxReferences,
const UA_BrowseDescription *bd) {
UA_BrowseResult result;
UA_BrowseResult_init(&result);
- UA_LOCK(server->serviceMutex);
+ UA_LOCK(&server->serviceMutex);
Operation_Browse(server, &server->adminSession, &maxReferences, bd, &result);
- UA_UNLOCK(server->serviceMutex);
+ UA_UNLOCK(&server->serviceMutex);
return result;
}
@@ -33142,7 +35715,8 @@ Operation_BrowseNext(UA_Server *server, UA_Session *session,
const UA_Boolean *releaseContinuationPoints,
const UA_ByteString *continuationPoint, UA_BrowseResult *result) {
/* Find the continuation point */
- ContinuationPoint **prev = &session->continuationPoints, *cp;
+ ContinuationPoint **prev = &session->continuationPoints;
+ ContinuationPoint *cp;
while((cp = *prev)) {
if(UA_ByteString_equal(&cp->identifier, continuationPoint))
break;
@@ -33171,7 +35745,8 @@ Operation_BrowseNext(UA_Server *server, UA_Session *session,
++session->availableContinuationPoints;
} else {
/* Return the cp identifier */
- UA_StatusCode retval = UA_ByteString_copy(&cp->identifier, &result->continuationPoint);
+ UA_StatusCode retval =
+ UA_ByteString_copy(&cp->identifier, &result->continuationPoint);
if(retval != UA_STATUSCODE_GOOD) {
UA_BrowseResult_clear(result);
result->statusCode = retval;
@@ -33185,14 +35760,18 @@ Service_BrowseNext(UA_Server *server, UA_Session *session,
UA_BrowseNextResponse *response) {
UA_LOG_DEBUG_SESSION(&server->config.logger, session,
"Processing BrowseNextRequest");
- UA_LOCK_ASSERT(server->serviceMutex, 1);
+ UA_LOCK_ASSERT(&server->serviceMutex, 1);
- UA_Boolean releaseContinuationPoints = request->releaseContinuationPoints; /* request is const */
+ UA_Boolean releaseContinuationPoints =
+ request->releaseContinuationPoints; /* request is const */
response->responseHeader.serviceResult =
- UA_Server_processServiceOperations(server, session, (UA_ServiceOperation)Operation_BrowseNext,
+ UA_Server_processServiceOperations(server, session,
+ (UA_ServiceOperation)Operation_BrowseNext,
&releaseContinuationPoints,
- &request->continuationPointsSize, &UA_TYPES[UA_TYPES_BYTESTRING],
- &response->resultsSize, &UA_TYPES[UA_TYPES_BROWSERESULT]);
+ &request->continuationPointsSize,
+ &UA_TYPES[UA_TYPES_BYTESTRING],
+ &response->resultsSize,
+ &UA_TYPES[UA_TYPES_BROWSERESULT]);
}
UA_BrowseResult
@@ -33200,10 +35779,10 @@ UA_Server_browseNext(UA_Server *server, UA_Boolean releaseContinuationPoint,
const UA_ByteString *continuationPoint) {
UA_BrowseResult result;
UA_BrowseResult_init(&result);
- UA_LOCK(server->serviceMutex);
+ UA_LOCK(&server->serviceMutex);
Operation_BrowseNext(server, &server->adminSession, &releaseContinuationPoint,
continuationPoint, &result);
- UA_UNLOCK(server->serviceMutex);
+ UA_UNLOCK(&server->serviceMutex);
return result;
}
@@ -33211,46 +35790,50 @@ UA_Server_browseNext(UA_Server *server, UA_Boolean releaseContinuationPoint,
/* TranslateBrowsePath */
/***********************/
+/* Find all entries for that hash. There are duplicate for the possible hash
+ * collisions. The exact browsename is checked afterwards. */
static UA_StatusCode
-addBrowseTarget(RefTree *next, const UA_ReferenceTarget *rt) {
+recursiveAddBrowseHashTarget(RefTree *results, struct aa_head *head,
+ const UA_ReferenceTarget *rt) {
UA_assert(rt);
- UA_StatusCode res = RefTree_add(next, &rt->targetId);
- UA_ReferenceTarget *left = ZIP_LEFT(rt, nameTreeFields);
- if(left && left->targetNameHash == rt->targetNameHash)
- res |= addBrowseTarget(next, left);
- UA_ReferenceTarget *right = ZIP_RIGHT(rt, nameTreeFields);
- if(right && right->targetNameHash == rt->targetNameHash)
- res |= addBrowseTarget(next, right);
+ UA_StatusCode res = RefTree_add(results, rt->targetId, NULL);
+ UA_ReferenceTarget *prev = (UA_ReferenceTarget*)aa_prev(head, rt);
+ while(prev && prev->targetNameHash == rt->targetNameHash) {
+ res |= RefTree_add(results, prev->targetId, NULL);
+ prev = (UA_ReferenceTarget*)aa_prev(head, prev);
+ }
+ UA_ReferenceTarget *next= (UA_ReferenceTarget*)aa_next(head, rt);
+ while(next && next->targetNameHash == rt->targetNameHash) {
+ res |= RefTree_add(results, next->targetId, NULL);
+ next = (UA_ReferenceTarget*)aa_next(head, next);
+ }
return res;
}
static UA_StatusCode
walkBrowsePathElement(UA_Server *server, UA_Session *session,
- const UA_RelativePath *path, const size_t pathIndex, UA_UInt32 nodeClassMask,
- const UA_QualifiedName *lastBrowseName, UA_BrowsePathResult *result,
- RefTree *current, RefTree *next) {
+ const UA_RelativePath *path, const size_t pathIndex,
+ UA_UInt32 nodeClassMask, const UA_QualifiedName *lastBrowseName,
+ UA_BrowsePathResult *result, RefTree *current, RefTree *next) {
/* For the next level. Note the difference from lastBrowseName */
const UA_RelativePathElement *elem = &path->elements[pathIndex];
UA_UInt32 browseNameHash = UA_QualifiedName_hash(&elem->targetName);
- /* Is the ReferenceType valid? */
- UA_Boolean all_refs = UA_NodeId_isNull(&elem->referenceTypeId);
- if(!all_refs) {
- const UA_Node *rootRef = UA_NODESTORE_GET(server, &elem->referenceTypeId);
- if(!rootRef)
- return UA_STATUSCODE_BADNOMATCH;
- UA_Boolean match = (rootRef->nodeClass == UA_NODECLASS_REFERENCETYPE);
- UA_NODESTORE_RELEASE(server, rootRef);
- if(!match)
- return UA_STATUSCODE_BADNOMATCH;
- }
+ /* Get the relevant ReferenceTypes */
+ UA_ReferenceTypeSet refTypes;
+ UA_StatusCode res =
+ referenceTypeIndices(server, &elem->referenceTypeId,
+ &refTypes, elem->includeSubtypes);
+ if(res != UA_STATUSCODE_GOOD)
+ return UA_STATUSCODE_BADNOMATCH;
- /* Loop over all Nodes int the current depth level */
- UA_StatusCode res = UA_STATUSCODE_GOOD;
+ struct aa_head _refNameTree = refNameTree;
+
+ /* Loop over all Nodes in the current depth level */
for(size_t i = 0; i < current->size; i++) {
- /* Remote Node. Immediately add to the results with the RemainingPathIndex set. */
- if(current->targets[i].serverIndex > 0 ||
- current->targets[i].namespaceUri.length > 0) {
+ /* Remote Node. Immediately add to the results with the
+ * RemainingPathIndex set. */
+ if(!UA_ExpandedNodeId_isLocal(&current->targets[i])) {
/* Increase the size of the results array */
UA_BrowsePathTarget *tmpResults = (UA_BrowsePathTarget*)
UA_realloc(result->targets, sizeof(UA_BrowsePathTarget) *
@@ -33277,9 +35860,10 @@ walkBrowsePathElement(UA_Server *server, UA_Session *session,
/* Test whether the node fits the class mask */
UA_Boolean skip = !matchClassMask(node, nodeClassMask);
- /* Does the BrowseName match for the current node (not the rerences
+ /* Does the BrowseName match for the current node (not the references
* going out here) */
- skip |= (lastBrowseName && !UA_QualifiedName_equal(lastBrowseName, &node->browseName));
+ skip |= (lastBrowseName &&
+ !UA_QualifiedName_equal(lastBrowseName, &node->head.browseName));
if(skip) {
UA_NODESTORE_RELEASE(server, node);
@@ -33287,36 +35871,45 @@ walkBrowsePathElement(UA_Server *server, UA_Session *session,
}
/* Loop over the ReferenceKinds */
- for(size_t j = 0; j < node->referencesSize; j++) {
- UA_NodeReferenceKind *rk = &node->references[j];
+ for(size_t j = 0; j < node->head.referencesSize; j++) {
+ UA_NodeReferenceKind *rk = &node->head.references[j];
/* Does the direction of the reference match? */
if(rk->isInverse != elem->isInverse)
continue;
/* Does the reference type match? */
- if(!all_refs) {
- if(!elem->includeSubtypes) {
- if(!UA_NodeId_equal(&rk->referenceTypeId, &elem->referenceTypeId))
- continue;
- } else {
- UA_Boolean match =
- isNodeInTree(server, &rk->referenceTypeId,
- &elem->referenceTypeId, &subtypeId, 1);
- if(!match)
+ if(!UA_ReferenceTypeSet_contains(&refTypes, rk->referenceTypeIndex))
+ continue;
+
+ if(rk->hasRefTree) {
+ /* Retrieve by BrowseName hash. We might have several nodes where
+ * the hash matches. The exact BrowseName will be verified in the
+ * next iteration of the outer loop. So we only have to retrieve
+ * every node just once. */
+ _refNameTree.root = rk->targets.tree.nameTreeRoot;
+ UA_ReferenceTarget *rt = (UA_ReferenceTarget*)
+ aa_find(&_refNameTree, &browseNameHash);
+ if(!rt)
+ continue;
+
+ res = recursiveAddBrowseHashTarget(next, &_refNameTree, rt);
+ if(res != UA_STATUSCODE_GOOD)
+ break;
+ } else {
+ /* The array entries don't have a BrowseName hash. Add all of
+ * them at this level to be checked with a full string
+ * comparison. */
+ for(size_t k = 0; k < rk->targetsSize; k++) {
+ if(rk->targets.array[k].targetNameHash != browseNameHash)
continue;
+ res = RefTree_add(next, rk->targets.array[k].targetId, NULL);
+ if(res != UA_STATUSCODE_GOOD)
+ break;
}
+ if(res != UA_STATUSCODE_GOOD)
+ break;
}
-
- /* Retrieve by BrowseName hash */
- UA_ReferenceTarget *rt = ZIP_FIND(UA_ReferenceTargetNameTree,
- &rk->refTargetsNameTree, &browseNameHash);
- if(!rt)
- continue;
-
- res = addBrowseTarget(next, rt);
- if(res != UA_STATUSCODE_GOOD)
- break;
}
UA_NODESTORE_RELEASE(server, node);
@@ -33329,9 +35922,9 @@ Operation_TranslateBrowsePathToNodeIds(UA_Server *server, UA_Session *session,
const UA_UInt32 *nodeClassMask,
const UA_BrowsePath *path,
UA_BrowsePathResult *result) {
- UA_LOCK_ASSERT(server->serviceMutex, 1);
+ UA_LOCK_ASSERT(&server->serviceMutex, 1);
- if(path->relativePath.elementsSize <= 0) {
+ if(path->relativePath.elementsSize == 0) {
result->statusCode = UA_STATUSCODE_BADNOTHINGTODO;
return;
}
@@ -33353,23 +35946,25 @@ Operation_TranslateBrowsePathToNodeIds(UA_Server *server, UA_Session *session,
UA_NODESTORE_RELEASE(server, startingNode);
/* Create two RefTrees that are alternated between path elements */
- RefTree rt1, rt2, *current = &rt1, *next = &rt2, *tmp;
+ RefTree rt1;
+ RefTree rt2;
+ RefTree *current = &rt1;
+ RefTree *next = &rt2;
+ RefTree *tmp;
result->statusCode |= RefTree_init(&rt1);
result->statusCode |= RefTree_init(&rt2);
+ UA_BrowsePathTarget *tmpResults = NULL;
+ UA_QualifiedName *browseNameFilter = NULL;
if(result->statusCode != UA_STATUSCODE_GOOD)
goto cleanup;
/* Copy the starting node into next */
- UA_ExpandedNodeId startingNodeId;
- UA_ExpandedNodeId_init(&startingNodeId);
- startingNodeId.nodeId = path->startingNode;
- result->statusCode = RefTree_add(next, &startingNodeId);
+ result->statusCode = RefTree_addNodeId(next, &path->startingNode, NULL);
if(result->statusCode != UA_STATUSCODE_GOOD)
goto cleanup;
/* Walk the path elements. Retrieve the nodes only once from the NodeStore.
* Hence the BrowseName is checked with one element "delay". */
- UA_QualifiedName *browseNameFilter = NULL;
for(size_t i = 0; i < path->relativePath.elementsSize; i++) {
/* Switch the trees */
tmp = current;
@@ -33398,10 +35993,10 @@ Operation_TranslateBrowsePathToNodeIds(UA_Server *server, UA_Session *session,
}
/* Allocate space for the results array */
- UA_BrowsePathTarget *tmpResults = (UA_BrowsePathTarget*)
+ tmpResults = (UA_BrowsePathTarget*)
UA_realloc(result->targets, sizeof(UA_BrowsePathTarget) *
(result->targetsSize + next->size));
- if(!tmpResults) {
+ if(!tmpResults && next->size > 0) {
result->statusCode = UA_STATUSCODE_BADOUTOFMEMORY;
goto cleanup;
}
@@ -33412,7 +36007,7 @@ Operation_TranslateBrowsePathToNodeIds(UA_Server *server, UA_Session *session,
const UA_Node *node = UA_NODESTORE_GET(server, &next->targets[k].nodeId);
if(!node)
continue;
- UA_Boolean match = UA_QualifiedName_equal(browseNameFilter, &node->browseName);
+ UA_Boolean match = UA_QualifiedName_equal(browseNameFilter, &node->head.browseName);
UA_NODESTORE_RELEASE(server, node);
if(!match)
continue;
@@ -33445,7 +36040,7 @@ Operation_TranslateBrowsePathToNodeIds(UA_Server *server, UA_Session *session,
UA_BrowsePathResult
translateBrowsePathToNodeIds(UA_Server *server,
const UA_BrowsePath *browsePath) {
- UA_LOCK_ASSERT(server->serviceMutex, 1);
+ UA_LOCK_ASSERT(&server->serviceMutex, 1);
UA_BrowsePathResult result;
UA_BrowsePathResult_init(&result);
UA_UInt32 nodeClassMask = 0; /* All node classes */
@@ -33457,9 +36052,9 @@ translateBrowsePathToNodeIds(UA_Server *server,
UA_BrowsePathResult
UA_Server_translateBrowsePathToNodeIds(UA_Server *server,
const UA_BrowsePath *browsePath) {
- UA_LOCK(server->serviceMutex);
+ UA_LOCK(&server->serviceMutex);
UA_BrowsePathResult result = translateBrowsePathToNodeIds(server, browsePath);
- UA_UNLOCK(server->serviceMutex);
+ UA_UNLOCK(&server->serviceMutex);
return result;
}
@@ -33469,7 +36064,7 @@ Service_TranslateBrowsePathsToNodeIds(UA_Server *server, UA_Session *session,
UA_TranslateBrowsePathsToNodeIdsResponse *response) {
UA_LOG_DEBUG_SESSION(&server->config.logger, session,
"Processing TranslateBrowsePathsToNodeIdsRequest");
- UA_LOCK_ASSERT(server->serviceMutex, 1);
+ UA_LOCK_ASSERT(&server->serviceMutex, 1);
/* Test the number of operations in the request */
if(server->config.maxNodesPerTranslateBrowsePathsToNodeIds != 0 &&
@@ -33490,13 +36085,23 @@ Service_TranslateBrowsePathsToNodeIds(UA_Server *server, UA_Session *session,
UA_BrowsePathResult
browseSimplifiedBrowsePath(UA_Server *server, const UA_NodeId origin,
size_t browsePathSize, const UA_QualifiedName *browsePath) {
- UA_LOCK_ASSERT(server->serviceMutex, 1);
+ UA_LOCK_ASSERT(&server->serviceMutex, 1);
+
+ UA_BrowsePathResult bpr;
+ UA_BrowsePathResult_init(&bpr);
+ if(browsePathSize > UA_MAX_TREE_RECURSE) {
+ UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Simplified Browse Path too long");
+ bpr.statusCode = UA_STATUSCODE_BADINTERNALERROR;
+ return bpr;
+ }
/* Construct the BrowsePath */
UA_BrowsePath bp;
UA_BrowsePath_init(&bp);
bp.startingNode = origin;
- UA_STACKARRAY(UA_RelativePathElement, rpe, browsePathSize);
+
+ UA_RelativePathElement rpe[UA_MAX_TREE_RECURSE];
memset(rpe, 0, sizeof(UA_RelativePathElement) * browsePathSize);
for(size_t j = 0; j < browsePathSize; j++) {
rpe[j].referenceTypeId = UA_NODEID_NUMERIC(0, UA_NS0ID_HIERARCHICALREFERENCES);
@@ -33507,12 +36112,7 @@ browseSimplifiedBrowsePath(UA_Server *server, const UA_NodeId origin,
bp.relativePath.elementsSize = browsePathSize;
/* Browse */
- UA_BrowsePathResult bpr;
- UA_BrowsePathResult_init(&bpr);
- UA_UInt32 nodeClassMask = UA_NODECLASS_OBJECT | UA_NODECLASS_VARIABLE;
-#ifdef UA_ENABLE_SUBSCRIPTIONS_ALARMS_CONDITIONS
- nodeClassMask |= UA_NODECLASS_OBJECTTYPE;
-#endif /* UA_ENABLE_SUBSCRIPTIONS_ALARMS_CONDITIONS */
+ UA_UInt32 nodeClassMask = UA_NODECLASS_OBJECT | UA_NODECLASS_VARIABLE | UA_NODECLASS_OBJECTTYPE;
Operation_TranslateBrowsePathToNodeIds(server, &server->adminSession, &nodeClassMask, &bp, &bpr);
return bpr;
@@ -33521,9 +36121,9 @@ browseSimplifiedBrowsePath(UA_Server *server, const UA_NodeId origin,
UA_BrowsePathResult
UA_Server_browseSimplifiedBrowsePath(UA_Server *server, const UA_NodeId origin,
size_t browsePathSize, const UA_QualifiedName *browsePath) {
- UA_LOCK(server->serviceMutex);
+ UA_LOCK(&server->serviceMutex);
UA_BrowsePathResult bpr = browseSimplifiedBrowsePath(server, origin, browsePathSize, browsePath);
- UA_UNLOCK(server->serviceMutex);
+ UA_UNLOCK(&server->serviceMutex);
return bpr;
}
@@ -33536,7 +36136,7 @@ void Service_RegisterNodes(UA_Server *server, UA_Session *session,
UA_RegisterNodesResponse *response) {
UA_LOG_DEBUG_SESSION(&server->config.logger, session,
"Processing RegisterNodesRequest");
- UA_LOCK_ASSERT(server->serviceMutex, 1);
+ UA_LOCK_ASSERT(&server->serviceMutex, 1);
//TODO: hang the nodeids to the session if really needed
if(request->nodesToRegisterSize == 0) {
@@ -33563,7 +36163,7 @@ void Service_UnregisterNodes(UA_Server *server, UA_Session *session,
UA_UnregisterNodesResponse *response) {
UA_LOG_DEBUG_SESSION(&server->config.logger, session,
"Processing UnRegisterNodesRequest");
- UA_LOCK_ASSERT(server->serviceMutex, 1);
+ UA_LOCK_ASSERT(&server->serviceMutex, 1);
//TODO: remove the nodeids from the session if really needed
if(request->nodesToUnregisterSize == 0)
@@ -33577,7 +36177,7 @@ void Service_UnregisterNodes(UA_Server *server, UA_Session *session,
}
}
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/src/server/ua_services_method.c" ***********************************/
+/**** amalgamated original file "/src/server/ua_services_method.c" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -33598,27 +36198,24 @@ void Service_UnregisterNodes(UA_Server *server, UA_Session *session,
#ifdef UA_ENABLE_METHODCALLS /* conditional compilation */
static const UA_VariableNode *
-getArgumentsVariableNode(UA_Server *server, const UA_MethodNode *ofMethod,
+getArgumentsVariableNode(UA_Server *server, const UA_NodeHead *head,
UA_String withBrowseName) {
- UA_NodeId hasProperty = UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY);
- for(size_t i = 0; i < ofMethod->referencesSize; ++i) {
- UA_NodeReferenceKind *rk = &ofMethod->references[i];
-
+ for(size_t i = 0; i < head->referencesSize; ++i) {
+ const UA_NodeReferenceKind *rk = &head->references[i];
if(rk->isInverse != false)
continue;
-
- if(!UA_NodeId_equal(&hasProperty, &rk->referenceTypeId))
+ if(rk->referenceTypeIndex != UA_REFERENCETYPEINDEX_HASPROPERTY)
continue;
-
- for(size_t j = 0; j < rk->refTargetsSize; ++j) {
+ const UA_ReferenceTarget *t = NULL;
+ while((t = UA_NodeReferenceKind_iterate(rk, t))) {
const UA_Node *refTarget =
- UA_NODESTORE_GET(server, &rk->refTargets[j].targetId.nodeId);
+ UA_NODESTORE_GETFROMREF(server, t->targetId);
if(!refTarget)
continue;
- if(refTarget->nodeClass == UA_NODECLASS_VARIABLE &&
- refTarget->browseName.namespaceIndex == 0 &&
- UA_String_equal(&withBrowseName, &refTarget->browseName.name)) {
- return (const UA_VariableNode*)refTarget;
+ if(refTarget->head.nodeClass == UA_NODECLASS_VARIABLE &&
+ refTarget->head.browseName.namespaceIndex == 0 &&
+ UA_String_equal(&withBrowseName, &refTarget->head.browseName.name)) {
+ return &refTarget->variableNode;
}
UA_NODESTORE_RELEASE(server, refTarget);
}
@@ -33653,10 +36250,20 @@ typeCheckArguments(UA_Server *server, UA_Session *session,
/* Type-check every argument against the definition */
UA_StatusCode retval = UA_STATUSCODE_GOOD;
UA_Argument *argReqs = (UA_Argument*)argRequirements->value.data.value.value.data;
+ const char *reason;
for(size_t i = 0; i < argReqsSize; ++i) {
+ if(compatibleValue(server, session, &argReqs[i].dataType, argReqs[i].valueRank,
+ argReqs[i].arrayDimensionsSize, argReqs[i].arrayDimensions,
+ &args[i], NULL, &reason))
+ continue;
+
+ /* Incompatible value. Try to correct the type if possible. */
+ adjustValueType(server, &args[i], &argReqs[i].dataType);
+
+ /* Recheck */
if(!compatibleValue(server, session, &argReqs[i].dataType, argReqs[i].valueRank,
argReqs[i].arrayDimensionsSize, argReqs[i].arrayDimensions,
- &args[i], NULL)) {
+ &args[i], NULL, &reason)) {
inputArgumentResults[i] = UA_STATUSCODE_BADTYPEMISMATCH;
retval = UA_STATUSCODE_BADINVALIDARGUMENT;
}
@@ -33671,7 +36278,7 @@ validMethodArguments(UA_Server *server, UA_Session *session, const UA_MethodNode
UA_StatusCode *inputArgumentResults) {
/* Get the input arguments node */
const UA_VariableNode *inputArguments =
- getArgumentsVariableNode(server, method, UA_STRING("InputArguments"));
+ getArgumentsVariableNode(server, &method->head, UA_STRING("InputArguments"));
if(!inputArguments) {
if(request->inputArgumentsSize > 0)
return UA_STATUSCODE_BADTOOMANYARGUMENTS;
@@ -33679,10 +36286,9 @@ validMethodArguments(UA_Server *server, UA_Session *session, const UA_MethodNode
}
/* Verify the request */
- UA_StatusCode retval = typeCheckArguments(server, session, inputArguments,
- request->inputArgumentsSize,
- request->inputArguments,
- inputArgumentResults);
+ UA_StatusCode retval =
+ typeCheckArguments(server, session, inputArguments, request->inputArgumentsSize,
+ request->inputArguments, inputArgumentResults);
/* Release the input arguments node */
UA_NODESTORE_RELEASE(server, (const UA_Node*)inputArguments);
@@ -33690,7 +36296,6 @@ validMethodArguments(UA_Server *server, UA_Session *session, const UA_MethodNode
}
static const UA_NodeId hasComponentNodeId = {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_HASCOMPONENT}};
-static const UA_NodeId hasSubTypeNodeId = {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_HASSUBTYPE}};
static const UA_NodeId organizedByNodeId = {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_ORGANIZES}};
static const UA_String namespaceDiModel = UA_STRING_STATIC("http://opcfoundation.org/UA/DI/");
static const UA_NodeId hasTypeDefinitionNodeId = {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_HASTYPEDEFINITION}};
@@ -33702,14 +36307,14 @@ callWithMethodAndObject(UA_Server *server, UA_Session *session,
const UA_CallMethodRequest *request, UA_CallMethodResult *result,
const UA_MethodNode *method, const UA_ObjectNode *object) {
/* Verify the object's NodeClass */
- if(object->nodeClass != UA_NODECLASS_OBJECT &&
- object->nodeClass != UA_NODECLASS_OBJECTTYPE) {
+ if(object->head.nodeClass != UA_NODECLASS_OBJECT &&
+ object->head.nodeClass != UA_NODECLASS_OBJECTTYPE) {
result->statusCode = UA_STATUSCODE_BADNODECLASSINVALID;
return;
}
/* Verify the method's NodeClass */
- if(method->nodeClass != UA_NODECLASS_METHOD) {
+ if(method->head.nodeClass != UA_NODECLASS_METHOD) {
result->statusCode = UA_STATUSCODE_BADNODECLASSINVALID;
return;
}
@@ -33720,20 +36325,28 @@ callWithMethodAndObject(UA_Server *server, UA_Session *session,
return;
}
+ UA_NodePointer methodP = UA_NodePointer_fromNodeId(&request->methodId);
+
/* Verify method/object relations. Object must have a hasComponent or a
* subtype of hasComponent reference to the method node. Therefore, check
* every reference between the parent object and the method node if there is
* a hasComponent (or subtype) reference */
+ UA_ReferenceTypeSet hasComponentRefs;
+ result->statusCode =
+ referenceTypeIndices(server, &hasComponentNodeId, &hasComponentRefs, true);
+ if(result->statusCode != UA_STATUSCODE_GOOD)
+ return;
+
UA_Boolean found = false;
- for(size_t i = 0; i < object->referencesSize && !found; ++i) {
- UA_NodeReferenceKind *rk = &object->references[i];
+ for(size_t i = 0; i < object->head.referencesSize && !found; ++i) {
+ const UA_NodeReferenceKind *rk = &object->head.references[i];
if(rk->isInverse)
continue;
- if(!isNodeInTree(server, &rk->referenceTypeId,
- &hasComponentNodeId, &hasSubTypeNodeId, 1))
+ if(!UA_ReferenceTypeSet_contains(&hasComponentRefs, rk->referenceTypeIndex))
continue;
- for(size_t j = 0; j < rk->refTargetsSize; ++j) {
- if(UA_NodeId_equal(&rk->refTargets[j].targetId.nodeId, &request->methodId)) {
+ const UA_ReferenceTarget *t = NULL;
+ while((t = UA_NodeReferenceKind_iterate(rk, t))) {
+ if(UA_NodePointer_equal(t->targetId, methodP)) {
found = true;
break;
}
@@ -33761,35 +36374,48 @@ callWithMethodAndObject(UA_Server *server, UA_Session *session,
}
functionGroupNodeId.namespaceIndex = (UA_UInt16)foundNamespace;
+ UA_ReferenceTypeSet hasTypeDefinitionRefs;
+ result->statusCode =
+ referenceTypeIndices(server, &hasTypeDefinitionNodeId,
+ &hasTypeDefinitionRefs, true);
+ if(result->statusCode != UA_STATUSCODE_GOOD)
+ return;
+
/* Search for a HasTypeDefinition (or sub-) reference in the parent object */
- for(size_t i = 0; i < object->referencesSize && !found; ++i) {
- UA_NodeReferenceKind *rk = &object->references[i];
+ for(size_t i = 0; i < object->head.referencesSize && !found; ++i) {
+ const UA_NodeReferenceKind *rk = &object->head.references[i];
if(rk->isInverse)
continue;
- if(!isNodeInTree(server, &rk->referenceTypeId,
- &hasTypeDefinitionNodeId, &hasSubTypeNodeId, 1))
+ if(!UA_ReferenceTypeSet_contains(&hasTypeDefinitionRefs, rk->referenceTypeIndex))
continue;
/* Verify that the HasTypeDefinition is equal to FunctionGroupType
* (or sub-type) from the DI model */
- for(size_t j = 0; j < rk->refTargetsSize && !found; ++j) {
- if(!isNodeInTree(server, &rk->refTargets[j].targetId.nodeId,
- &functionGroupNodeId, &hasSubTypeNodeId, 1))
+ const UA_ReferenceTarget *t = NULL;
+ while((t = UA_NodeReferenceKind_iterate(rk, t))) {
+ if(!UA_NodePointer_isLocal(t->targetId))
continue;
+ UA_NodeId tmpId = UA_NodePointer_toNodeId(t->targetId);
+ if(!isNodeInTree_singleRef(server, &tmpId, &functionGroupNodeId,
+ UA_REFERENCETYPEINDEX_HASSUBTYPE))
+ continue;
+
/* Search for the called method with reference Organize (or
* sub-type) from the parent object */
- for(size_t k = 0; k < object->referencesSize && !found; ++k) {
- UA_NodeReferenceKind *rkInner = &object->references[k];
+ for(size_t k = 0; k < object->head.referencesSize && !found; ++k) {
+ const UA_NodeReferenceKind *rkInner = &object->head.references[k];
if(rkInner->isInverse)
continue;
- if(!isNodeInTree(server, &rkInner->referenceTypeId,
- &organizedByNodeId, &hasSubTypeNodeId, 1))
+ const UA_NodeId * refId =
+ UA_NODESTORE_GETREFERENCETYPEID(server, rkInner->referenceTypeIndex);
+ if(!isNodeInTree_singleRef(server, refId, &organizedByNodeId,
+ UA_REFERENCETYPEINDEX_HASSUBTYPE))
continue;
- for(size_t m = 0; m < rkInner->refTargetsSize; ++m) {
- if(UA_NodeId_equal(&rkInner->refTargets[m].targetId.nodeId,
- &request->methodId)) {
+ const UA_ReferenceTarget *t2 = NULL;
+ while((t2 = UA_NodeReferenceKind_iterate(rkInner, t2))) {
+ if(UA_NodePointer_equal(t2->targetId, methodP)) {
found = true;
break;
}
@@ -33806,12 +36432,12 @@ callWithMethodAndObject(UA_Server *server, UA_Session *session,
/* Verify access rights */
UA_Boolean executable = method->executable;
if(session != &server->adminSession) {
- UA_UNLOCK(server->serviceMutex);
+ UA_UNLOCK(&server->serviceMutex);
executable = executable && server->config.accessControl.
getUserExecutableOnObject(server, &server->config.accessControl, &session->sessionId,
- session->sessionHandle, &request->methodId, method->context,
- &request->objectId, object->context);
- UA_LOCK(server->serviceMutex);
+ session->sessionHandle, &request->methodId, method->head.context,
+ &request->objectId, object->head.context);
+ UA_LOCK(&server->serviceMutex);
}
if(!executable) {
@@ -33829,7 +36455,8 @@ callWithMethodAndObject(UA_Server *server, UA_Session *session,
result->inputArgumentResultsSize = request->inputArgumentsSize;
/* Verify Input Arguments */
- result->statusCode = validMethodArguments(server, session, method, request, result->inputArgumentResults);
+ result->statusCode = validMethodArguments(server, session, method, request,
+ result->inputArgumentResults);
/* Return inputArgumentResults only for BADINVALIDARGUMENT */
if(result->statusCode != UA_STATUSCODE_BADINVALIDARGUMENT) {
@@ -33845,7 +36472,7 @@ callWithMethodAndObject(UA_Server *server, UA_Session *session,
/* Get the output arguments node */
const UA_VariableNode *outputArguments =
- getArgumentsVariableNode(server, method, UA_STRING("OutputArguments"));
+ getArgumentsVariableNode(server, &method->head, UA_STRING("OutputArguments"));
/* Allocate the output arguments array */
size_t outputArgsSize = 0;
@@ -33863,13 +36490,13 @@ callWithMethodAndObject(UA_Server *server, UA_Session *session,
UA_NODESTORE_RELEASE(server, (const UA_Node*)outputArguments);
/* Call the method */
- UA_UNLOCK(server->serviceMutex);
+ UA_UNLOCK(&server->serviceMutex);
result->statusCode = method->method(server, &session->sessionId, session->sessionHandle,
- &method->nodeId, method->context,
- &object->nodeId, object->context,
+ &method->head.nodeId, method->head.context,
+ &object->head.nodeId, object->head.context,
request->inputArgumentsSize, request->inputArguments,
result->outputArgumentsSize, result->outputArguments);
- UA_LOCK(server->serviceMutex);
+ UA_LOCK(&server->serviceMutex);
/* TODO: Verify Output matches the argument definition */
}
@@ -33881,25 +36508,24 @@ Operation_CallMethodAsync(UA_Server *server, UA_Session *session, UA_UInt32 requ
UA_CallMethodRequest *opRequest, UA_CallMethodResult *opResult,
UA_AsyncResponse **ar) {
/* Get the method node */
- const UA_MethodNode *method = (const UA_MethodNode*)
- UA_NODESTORE_GET(server, &opRequest->methodId);
+ const UA_Node *method = UA_NODESTORE_GET(server, &opRequest->methodId);
if(!method) {
opResult->statusCode = UA_STATUSCODE_BADNODEIDUNKNOWN;
return;
}
/* Get the object node */
- const UA_ObjectNode *object = (const UA_ObjectNode*)
- UA_NODESTORE_GET(server, &opRequest->objectId);
+ const UA_Node *object = UA_NODESTORE_GET(server, &opRequest->objectId);
if(!object) {
opResult->statusCode = UA_STATUSCODE_BADNODEIDUNKNOWN;
- UA_NODESTORE_RELEASE(server, (const UA_Node*)method);
+ UA_NODESTORE_RELEASE(server, method);
return;
}
/* Synchronous execution */
- if(!method->async) {
- callWithMethodAndObject(server, session, opRequest, opResult, method, object);
+ if(!method->methodNode.async) {
+ callWithMethodAndObject(server, session, opRequest, opResult,
+ &method->methodNode, &object->objectNode);
goto cleanup;
}
@@ -33909,9 +36535,8 @@ Operation_CallMethodAsync(UA_Server *server, UA_Session *session, UA_UInt32 requ
if(!*ar) {
opResult->statusCode =
UA_AsyncManager_createAsyncResponse(&server->asyncManager, server,
- &session->sessionId, requestId,
- requestHandle, UA_ASYNCOPERATIONTYPE_CALL,
- ar);
+ &session->sessionId, requestId, requestHandle,
+ UA_ASYNCOPERATIONTYPE_CALL, ar);
if(opResult->statusCode != UA_STATUSCODE_GOOD)
goto cleanup;
}
@@ -33923,8 +36548,8 @@ Operation_CallMethodAsync(UA_Server *server, UA_Session *session, UA_UInt32 requ
cleanup:
/* Release the method and object node */
- UA_NODESTORE_RELEASE(server, (const UA_Node*)method);
- UA_NODESTORE_RELEASE(server, (const UA_Node*)object);
+ UA_NODESTORE_RELEASE(server, method);
+ UA_NODESTORE_RELEASE(server, object);
}
void
@@ -33941,23 +36566,21 @@ Service_CallAsync(UA_Server *server, UA_Session *session, UA_UInt32 requestId,
UA_AsyncResponse *ar = NULL;
response->responseHeader.serviceResult =
UA_Server_processServiceOperationsAsync(server, session, requestId,
- request->requestHeader.requestHandle,
- (UA_AsyncServiceOperation)Operation_CallMethodAsync,
- &request->methodsToCallSize,
- &UA_TYPES[UA_TYPES_CALLMETHODREQUEST],
- &response->resultsSize,
- &UA_TYPES[UA_TYPES_CALLMETHODRESULT], &ar);
+ request->requestHeader.requestHandle,
+ (UA_AsyncServiceOperation)Operation_CallMethodAsync,
+ &request->methodsToCallSize, &UA_TYPES[UA_TYPES_CALLMETHODREQUEST],
+ &response->resultsSize, &UA_TYPES[UA_TYPES_CALLMETHODRESULT], &ar);
if(ar) {
if(ar->opCountdown > 0) {
- /* Move all results to the AsyncResponse. The async operation results
- * will be overwritten when the workers return results. */
+ /* Move all results to the AsyncResponse. The async operation
+ * results will be overwritten when the workers return results. */
ar->response.callResponse = *response;
UA_CallResponse_init(response);
*finished = false;
} else {
- /* If there is a new AsyncResponse, ensure it has at least one pending
- * operation */
+ /* If there is a new AsyncResponse, ensure it has at least one
+ * pending operation */
UA_AsyncManager_removeAsyncResponse(&server->asyncManager, ar);
}
}
@@ -33968,35 +36591,33 @@ static void
Operation_CallMethod(UA_Server *server, UA_Session *session, void *context,
const UA_CallMethodRequest *request, UA_CallMethodResult *result) {
/* Get the method node */
- const UA_MethodNode *method = (const UA_MethodNode*)
- UA_NODESTORE_GET(server, &request->methodId);
+ const UA_Node *method = UA_NODESTORE_GET(server, &request->methodId);
if(!method) {
result->statusCode = UA_STATUSCODE_BADNODEIDUNKNOWN;
return;
}
/* Get the object node */
- const UA_ObjectNode *object = (const UA_ObjectNode*)
- UA_NODESTORE_GET(server, &request->objectId);
+ const UA_Node *object = UA_NODESTORE_GET(server, &request->objectId);
if(!object) {
result->statusCode = UA_STATUSCODE_BADNODEIDUNKNOWN;
- UA_NODESTORE_RELEASE(server, (const UA_Node*)method);
+ UA_NODESTORE_RELEASE(server, method);
return;
}
/* Continue with method and object as context */
- callWithMethodAndObject(server, session, request, result, method, object);
+ callWithMethodAndObject(server, session, request, result,
+ &method->methodNode, &object->objectNode);
/* Release the method and object node */
- UA_NODESTORE_RELEASE(server, (const UA_Node*)method);
- UA_NODESTORE_RELEASE(server, (const UA_Node*)object);
+ UA_NODESTORE_RELEASE(server, method);
+ UA_NODESTORE_RELEASE(server, object);
}
void Service_Call(UA_Server *server, UA_Session *session,
- const UA_CallRequest *request,
- UA_CallResponse *response) {
+ const UA_CallRequest *request, UA_CallResponse *response) {
UA_LOG_DEBUG_SESSION(&server->config.logger, session, "Processing CallRequest");
- UA_LOCK_ASSERT(server->serviceMutex, 1);
+ UA_LOCK_ASSERT(&server->serviceMutex, 1);
if(server->config.maxNodesPerMethodCall != 0 &&
request->methodsToCallSize > server->config.maxNodesPerMethodCall) {
@@ -34005,24 +36626,25 @@ void Service_Call(UA_Server *server, UA_Session *session,
}
response->responseHeader.serviceResult =
- UA_Server_processServiceOperations(server, session, (UA_ServiceOperation)Operation_CallMethod, NULL,
- &request->methodsToCallSize, &UA_TYPES[UA_TYPES_CALLMETHODREQUEST],
- &response->resultsSize, &UA_TYPES[UA_TYPES_CALLMETHODRESULT]);
+ UA_Server_processServiceOperations(server, session,
+ (UA_ServiceOperation)Operation_CallMethod, NULL,
+ &request->methodsToCallSize, &UA_TYPES[UA_TYPES_CALLMETHODREQUEST],
+ &response->resultsSize, &UA_TYPES[UA_TYPES_CALLMETHODRESULT]);
}
-UA_CallMethodResult UA_EXPORT
+UA_CallMethodResult
UA_Server_call(UA_Server *server, const UA_CallMethodRequest *request) {
UA_CallMethodResult result;
UA_CallMethodResult_init(&result);
- UA_LOCK(server->serviceMutex);
+ UA_LOCK(&server->serviceMutex);
Operation_CallMethod(server, &server->adminSession, NULL, request, &result);
- UA_UNLOCK(server->serviceMutex);
+ UA_UNLOCK(&server->serviceMutex);
return result;
}
#endif /* UA_ENABLE_METHODCALLS */
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/src/server/ua_services_session.c" ***********************************/
+/**** amalgamated original file "/src/server/ua_services_session.c" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -34043,9 +36665,9 @@ UA_Server_call(UA_Server *server, const UA_CallMethodRequest *request) {
/* Delayed callback to free the session memory */
static void
removeSessionCallback(UA_Server *server, session_list_entry *entry) {
- UA_LOCK(server->serviceMutex);
- UA_Session_deleteMembersCleanup(&entry->session, server);
- UA_UNLOCK(server->serviceMutex);
+ UA_LOCK(&server->serviceMutex);
+ UA_Session_clear(&entry->session, server);
+ UA_UNLOCK(&server->serviceMutex);
}
void
@@ -34053,57 +36675,59 @@ UA_Server_removeSession(UA_Server *server, session_list_entry *sentry,
UA_DiagnosticEvent event) {
UA_Session *session = &sentry->session;
- UA_LOCK_ASSERT(server->serviceMutex, 1);
+ UA_LOCK_ASSERT(&server->serviceMutex, 1);
/* Remove the Subscriptions */
#ifdef UA_ENABLE_SUBSCRIPTIONS
UA_Subscription *sub, *tempsub;
- LIST_FOREACH_SAFE(sub, &session->serverSubscriptions, listEntry, tempsub) {
- UA_Session_deleteSubscription(server, session, sub->subscriptionId);
+ TAILQ_FOREACH_SAFE(sub, &session->subscriptions, sessionListEntry, tempsub) {
+ UA_Subscription_delete(server, sub);
}
UA_PublishResponseEntry *entry;
while((entry = UA_Session_dequeuePublishReq(session))) {
- UA_PublishResponse_deleteMembers(&entry->response);
+ UA_PublishResponse_clear(&entry->response);
UA_free(entry);
}
#endif
/* Callback into userland access control */
if(server->config.accessControl.closeSession) {
- UA_UNLOCK(server->serviceMutex);
+ UA_UNLOCK(&server->serviceMutex);
server->config.accessControl.closeSession(server, &server->config.accessControl,
&session->sessionId, session->sessionHandle);
- UA_LOCK(server->serviceMutex);
+ UA_LOCK(&server->serviceMutex);
}
/* Detach the Session from the SecureChannel */
UA_Session_detachFromSecureChannel(session);
/* Deactivate the session */
- sentry->session.activated = false;
+ if(sentry->session.activated) {
+ sentry->session.activated = false;
+ server->activeSessionCount--;
+ }
/* Detach the session from the session manager and make the capacity
* available */
LIST_REMOVE(sentry, pointers);
- UA_atomic_subUInt32(&server->sessionCount, 1);
- UA_atomic_subSize(&server->serverStats.ss.currentSessionCount, 1);
+ server->sessionCount--;
switch(event) {
case UA_DIAGNOSTICEVENT_CLOSE:
case UA_DIAGNOSTICEVENT_PURGE:
break;
case UA_DIAGNOSTICEVENT_TIMEOUT:
- UA_atomic_addSize(&server->serverStats.ss.sessionTimeoutCount, 1);
+ server->serverDiagnosticsSummary.sessionTimeoutCount++;
break;
case UA_DIAGNOSTICEVENT_REJECT:
- UA_atomic_addSize(&server->serverStats.ss.rejectedSessionCount, 1);
+ server->serverDiagnosticsSummary.rejectedSessionCount++;
break;
case UA_DIAGNOSTICEVENT_SECURITYREJECT:
- UA_atomic_addSize(&server->serverStats.ss.securityRejectedSessionCount, 1);
+ server->serverDiagnosticsSummary.securityRejectedSessionCount++;
break;
case UA_DIAGNOSTICEVENT_ABORT:
- UA_atomic_addSize(&server->serverStats.ss.sessionAbortCount, 1);
+ server->serverDiagnosticsSummary.sessionAbortCount++;
break;
default:
UA_assert(false);
@@ -34115,13 +36739,15 @@ UA_Server_removeSession(UA_Server *server, session_list_entry *sentry,
sentry->cleanupCallback.callback = (UA_ApplicationCallback)removeSessionCallback;
sentry->cleanupCallback.application = server;
sentry->cleanupCallback.data = sentry;
- UA_WorkQueue_enqueueDelayed(&server->workQueue, &sentry->cleanupCallback);
+ sentry->cleanupCallback.nextTime = UA_DateTime_nowMonotonic() + 1;
+ sentry->cleanupCallback.interval = 0; /* Remove the structure */
+ UA_Timer_addTimerEntry(&server->timer, &sentry->cleanupCallback, NULL);
}
UA_StatusCode
UA_Server_removeSessionByToken(UA_Server *server, const UA_NodeId *token,
UA_DiagnosticEvent event) {
- UA_LOCK_ASSERT(server->serviceMutex, 1);
+ UA_LOCK_ASSERT(&server->serviceMutex, 1);
session_list_entry *entry;
LIST_FOREACH(entry, &server->sessions, pointers) {
if(UA_NodeId_equal(&entry->session.header.authenticationToken, token)) {
@@ -34134,7 +36760,7 @@ UA_Server_removeSessionByToken(UA_Server *server, const UA_NodeId *token,
void
UA_Server_cleanupSessions(UA_Server *server, UA_DateTime nowMonotonic) {
- UA_LOCK_ASSERT(server->serviceMutex, 1);
+ UA_LOCK_ASSERT(&server->serviceMutex, 1);
session_list_entry *sentry, *temp;
LIST_FOREACH_SAFE(sentry, &server->sessions, pointers, temp) {
/* Session has timed out? */
@@ -34151,7 +36777,7 @@ UA_Server_cleanupSessions(UA_Server *server, UA_DateTime nowMonotonic) {
UA_Session *
getSessionByToken(UA_Server *server, const UA_NodeId *token) {
- UA_LOCK_ASSERT(server->serviceMutex, 1);
+ UA_LOCK_ASSERT(&server->serviceMutex, 1);
session_list_entry *current = NULL;
LIST_FOREACH(current, &server->sessions, pointers) {
@@ -34174,7 +36800,7 @@ getSessionByToken(UA_Server *server, const UA_NodeId *token) {
UA_Session *
UA_Server_getSessionById(UA_Server *server, const UA_NodeId *sessionId) {
- UA_LOCK_ASSERT(server->serviceMutex, 1);
+ UA_LOCK_ASSERT(&server->serviceMutex, 1);
session_list_entry *current = NULL;
LIST_FOREACH(current, &server->sessions, pointers) {
@@ -34208,7 +36834,7 @@ signCreateSessionResponse(UA_Server *server, UA_SecureChannel *channel,
/* Prepare the signature */
size_t signatureSize = securityPolicy->certificateSigningAlgorithm.
- getLocalSignatureSize(securityPolicy, channel->channelContext);
+ getLocalSignatureSize(channel->channelContext);
UA_StatusCode retval = UA_String_copy(&securityPolicy->certificateSigningAlgorithm.uri,
&signatureData->algorithm);
retval |= UA_ByteString_allocBuffer(&signatureData->signature, signatureSize);
@@ -34227,7 +36853,7 @@ signCreateSessionResponse(UA_Server *server, UA_SecureChannel *channel,
memcpy(dataToSign.data + request->clientCertificate.length,
request->clientNonce.data, request->clientNonce.length);
retval = securityPolicy->certificateSigningAlgorithm.
- sign(securityPolicy, channel->channelContext, &dataToSign, &signatureData->signature);
+ sign(channel->channelContext, &dataToSign, &signatureData->signature);
/* Clean up */
UA_ByteString_clear(&dataToSign);
@@ -34238,32 +36864,38 @@ signCreateSessionResponse(UA_Server *server, UA_SecureChannel *channel,
UA_StatusCode
UA_Server_createSession(UA_Server *server, UA_SecureChannel *channel,
const UA_CreateSessionRequest *request, UA_Session **session) {
- UA_LOCK_ASSERT(server->serviceMutex, 1);
+ UA_LOCK_ASSERT(&server->serviceMutex, 1);
- if(server->sessionCount >= server->config.maxSessions)
+ if(server->sessionCount >= server->config.maxSessions) {
+ UA_LOG_WARNING_CHANNEL(&server->config.logger, channel,
+ "Could not create a Session - Server limits reached");
return UA_STATUSCODE_BADTOOMANYSESSIONS;
+ }
- session_list_entry *newentry = (session_list_entry *)UA_malloc(sizeof(session_list_entry));
+ session_list_entry *newentry = (session_list_entry*)
+ UA_malloc(sizeof(session_list_entry));
if(!newentry)
return UA_STATUSCODE_BADOUTOFMEMORY;
- UA_atomic_addUInt32(&server->sessionCount, 1);
+ /* Initialize the Session */
UA_Session_init(&newentry->session);
newentry->session.sessionId = UA_NODEID_GUID(1, UA_Guid_random());
newentry->session.header.authenticationToken = UA_NODEID_GUID(1, UA_Guid_random());
+ newentry->session.timeout = server->config.maxSessionTimeout;
if(request->requestedSessionTimeout <= server->config.maxSessionTimeout &&
request->requestedSessionTimeout > 0)
newentry->session.timeout = request->requestedSessionTimeout;
- else
- newentry->session.timeout = server->config.maxSessionTimeout;
/* Attach the session to the channel. But don't activate for now. */
if(channel)
UA_Session_attachToSecureChannel(&newentry->session, channel);
UA_Session_updateLifetime(&newentry->session);
+ /* Add to the server */
LIST_INSERT_HEAD(&server->sessions, newentry, pointers);
+ server->sessionCount++;
+
*session = &newentry->session;
return UA_STATUSCODE_GOOD;
}
@@ -34272,7 +36904,7 @@ void
Service_CreateSession(UA_Server *server, UA_SecureChannel *channel,
const UA_CreateSessionRequest *request,
UA_CreateSessionResponse *response) {
- UA_LOCK_ASSERT(server->serviceMutex, 1);
+ UA_LOCK_ASSERT(&server->serviceMutex, 1);
UA_LOG_DEBUG_CHANNEL(&server->config.logger, channel, "Trying to create session");
if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGN ||
@@ -34311,8 +36943,8 @@ Service_CreateSession(UA_Server *server, UA_SecureChannel *channel,
if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
UA_LOG_WARNING_CHANNEL(&server->config.logger, channel,
"The client's ApplicationURI did not match the certificate");
- UA_atomic_addSize(&server->serverStats.ss.securityRejectedSessionCount, 1);
- UA_atomic_addSize(&server->serverStats.ss.rejectedSessionCount, 1);
+ server->serverDiagnosticsSummary.securityRejectedSessionCount++;
+ server->serverDiagnosticsSummary.rejectedSessionCount++;
return;
}
}
@@ -34323,6 +36955,7 @@ Service_CreateSession(UA_Server *server, UA_SecureChannel *channel,
if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
UA_LOG_WARNING_CHANNEL(&server->config.logger, channel,
"Processing CreateSessionRequest failed");
+ server->serverDiagnosticsSummary.rejectedSessionCount++;
return;
}
@@ -34372,6 +37005,13 @@ Service_CreateSession(UA_Server *server, UA_SecureChannel *channel,
response->responseHeader.serviceResult |=
UA_String_copy(&request->sessionName, &newSession->sessionName);
+#ifdef UA_ENABLE_DIAGNOSTICS
+ response->responseHeader.serviceResult |=
+ UA_String_copy(&request->serverUri, &newSession->diagnostics.serverUri);
+ response->responseHeader.serviceResult |=
+ UA_String_copy(&request->endpointUrl, &newSession->diagnostics.endpointUrl);
+#endif
+
UA_ByteString_init(&response->serverCertificate);
if(server->config.endpointsSize > 0)
@@ -34404,45 +37044,48 @@ Service_CreateSession(UA_Server *server, UA_SecureChannel *channel,
return;
}
- UA_LOG_INFO_CHANNEL(&server->config.logger, channel,
- "Session " UA_PRINTF_GUID_FORMAT " created",
- UA_PRINTF_GUID_DATA(newSession->sessionId.identifier.guid));
+#ifdef UA_ENABLE_DIAGNOSTICS
+ newSession->diagnostics.clientConnectionTime = UA_DateTime_now();
+ newSession->diagnostics.clientLastContactTime =
+ newSession->diagnostics.clientConnectionTime;
+
+ /* Create the object in the information model */
+ createSessionObject(server, newSession);
+#endif
+
+ UA_LOG_INFO_SESSION(&server->config.logger, newSession, "Session created");
}
static UA_StatusCode
-checkSignature(const UA_Server *server, const UA_SecureChannel *channel,
- UA_Session *session, const UA_ActivateSessionRequest *request) {
- if(channel->securityMode != UA_MESSAGESECURITYMODE_SIGN &&
- channel->securityMode != UA_MESSAGESECURITYMODE_SIGNANDENCRYPT)
- return UA_STATUSCODE_GOOD;
-
- /* Check for zero signature length in client signature */
- if(request->clientSignature.signature.length == 0)
+checkSignature(const UA_Server *server, const UA_SecurityPolicy *securityPolicy,
+ void *channelContext, const UA_ByteString *serverNonce,
+ const UA_SignatureData *signature) {
+ /* Check for zero signature length */
+ if(signature->signature.length == 0)
return UA_STATUSCODE_BADAPPLICATIONSIGNATUREINVALID;
- if(!channel->securityPolicy)
+ if(!securityPolicy)
return UA_STATUSCODE_BADINTERNALERROR;
- const UA_SecurityPolicy *securityPolicy = channel->securityPolicy;
const UA_ByteString *localCertificate = &securityPolicy->localCertificate;
-
+ /* Data to verify is calculated by appending the serverNonce to the local certificate */
UA_ByteString dataToVerify;
- size_t dataToVerifySize = localCertificate->length + session->serverNonce.length;
+ size_t dataToVerifySize = localCertificate->length + serverNonce->length;
UA_StatusCode retval = UA_ByteString_allocBuffer(&dataToVerify, dataToVerifySize);
if(retval != UA_STATUSCODE_GOOD)
return retval;
memcpy(dataToVerify.data, localCertificate->data, localCertificate->length);
memcpy(dataToVerify.data + localCertificate->length,
- session->serverNonce.data, session->serverNonce.length);
+ serverNonce->data, serverNonce->length);
retval = securityPolicy->certificateSigningAlgorithm.
- verify(securityPolicy, channel->channelContext, &dataToVerify,
- &request->clientSignature.signature);
+ verify(channelContext, &dataToVerify, &signature->signature);
UA_ByteString_clear(&dataToVerify);
return retval;
}
#ifdef UA_ENABLE_ENCRYPTION
+
static UA_StatusCode
decryptPassword(UA_SecurityPolicy *securityPolicy, void *tempChannelContext,
const UA_ByteString *serverNonce, UA_UserNameIdentityToken *userToken) {
@@ -34453,15 +37096,15 @@ decryptPassword(UA_SecurityPolicy *securityPolicy, void *tempChannelContext,
UA_UInt32 tokenSecretLength;
UA_ByteString decryptedTokenSecret, tokenServerNonce;
+ size_t tokenpos = 0;
+ size_t offset = 0;
if(UA_ByteString_copy(&userToken->password, &decryptedTokenSecret) != UA_STATUSCODE_GOOD)
return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
UA_StatusCode retval = UA_STATUSCODE_BADIDENTITYTOKENINVALID;
- if(asymEnc->decrypt(securityPolicy, tempChannelContext,
- &decryptedTokenSecret) != UA_STATUSCODE_GOOD)
+ if(asymEnc->decrypt(tempChannelContext, &decryptedTokenSecret) != UA_STATUSCODE_GOOD)
goto cleanup;
- size_t offset = 0;
UA_UInt32_decodeBinary(&decryptedTokenSecret, &offset, &tokenSecretLength);
/* The decrypted data must be large enough to include the Encrypted Token
@@ -34481,7 +37124,7 @@ decryptPassword(UA_SecurityPolicy *securityPolicy, void *tempChannelContext,
/* The server nonce must match according to the 1.04.1 specification errata,
* chapter 3. */
- size_t tokenpos = sizeof(UA_UInt32) + tokenSecretLength - serverNonce->length;
+ tokenpos = sizeof(UA_UInt32) + tokenSecretLength - serverNonce->length;
tokenServerNonce.length = serverNonce->length;
tokenServerNonce.data = &decryptedTokenSecret.data[tokenpos];
if(!UA_ByteString_equal(serverNonce, &tokenServerNonce))
@@ -34567,6 +37210,42 @@ selectEndpointAndTokenPolicy(UA_Server *server, UA_SecureChannel *channel,
}
}
+#ifdef UA_ENABLE_DIAGNOSTICS
+static UA_StatusCode
+saveClientUserId(const UA_ExtensionObject *userIdentityToken,
+ UA_SessionSecurityDiagnosticsDataType *diag) {
+ UA_StatusCode res = UA_STATUSCODE_GOOD;
+
+ UA_String_clear(&diag->clientUserIdOfSession);
+ if(userIdentityToken->encoding != UA_EXTENSIONOBJECT_DECODED)
+ return UA_STATUSCODE_GOOD;
+
+ if(userIdentityToken->content.decoded.type ==
+ &UA_TYPES[UA_TYPES_ANONYMOUSIDENTITYTOKEN]) {
+ /* String of length 0 */
+ } else if(userIdentityToken->content.decoded.type ==
+ &UA_TYPES[UA_TYPES_USERNAMEIDENTITYTOKEN]) {
+ const UA_UserNameIdentityToken *userToken = (UA_UserNameIdentityToken*)
+ userIdentityToken->content.decoded.data;
+ res = UA_String_copy(&userToken->userName, &diag->clientUserIdOfSession);
+ } else if(userIdentityToken->content.decoded.type ==
+ &UA_TYPES[UA_TYPES_X509IDENTITYTOKEN]) {
+ /* TODO: return the X509 Subject Name of the certificate */
+ } else {
+ return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
+ }
+
+ if(res != UA_STATUSCODE_GOOD)
+ return res;
+
+ return UA_Array_appendCopy((void**)&diag->clientUserIdHistory,
+ &diag->clientUserIdHistorySize,
+ &diag->clientUserIdOfSession,
+ &UA_TYPES[UA_TYPES_STRING]);
+}
+#endif
+
+
/* TODO: Check all of the following: The Server shall verify that the
* Certificate the Client used to create the new SecureChannel is the same as
* the Certificate used to create the original SecureChannel. In addition, the
@@ -34579,7 +37258,10 @@ void
Service_ActivateSession(UA_Server *server, UA_SecureChannel *channel,
const UA_ActivateSessionRequest *request,
UA_ActivateSessionResponse *response) {
- UA_LOCK_ASSERT(server->serviceMutex, 1);
+ const UA_EndpointDescription *ed = NULL;
+ const UA_UserTokenPolicy *utp = NULL;
+ UA_String *tmpLocaleIds;
+ UA_LOCK_ASSERT(&server->serviceMutex, 1);
UA_Session *session = getSessionByToken(server, &request->requestHeader.authenticationToken);
if(!session) {
@@ -34610,19 +37292,21 @@ Service_ActivateSession(UA_Server *server, UA_SecureChannel *channel,
goto rejected;
}
- /* Check if the signature corresponds to the ServerNonce that was last sent
- * to the client */
- response->responseHeader.serviceResult = checkSignature(server, channel, session, request);
- if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
- UA_LOG_WARNING_SESSION(&server->config.logger, session,
- "ActivateSession: Signature check failed with StatusCode %s",
- UA_StatusCode_name(response->responseHeader.serviceResult));
- goto securityRejected;
+ /* Check the client signature */
+ if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGN ||
+ channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) {
+ response->responseHeader.serviceResult =
+ checkSignature(server, channel->securityPolicy, channel->channelContext,
+ &session->serverNonce, &request->clientSignature);
+ if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
+ UA_LOG_WARNING_SESSION(&server->config.logger, session,
+ "ActivateSession: Client signature check failed with StatusCode %s",
+ UA_StatusCode_name(response->responseHeader.serviceResult));
+ goto securityRejected;
+ }
}
/* Find the matching Endpoint with UserTokenPolicy */
- const UA_EndpointDescription *ed = NULL;
- const UA_UserTokenPolicy *utp = NULL;
selectEndpointAndTokenPolicy(server, channel, &request->userIdentityToken, &ed, &utp);
if(!ed) {
response->responseHeader.serviceResult = UA_STATUSCODE_BADIDENTITYTOKENINVALID;
@@ -34638,12 +37322,12 @@ Service_ActivateSession(UA_Server *server, UA_SecureChannel *channel,
* policy of the secure channel is used. */
UA_SecurityPolicy* securityPolicy;
if(!utp->securityPolicyUri.data)
- securityPolicy = UA_SecurityPolicy_getSecurityPolicyByUri(server, &ed->securityPolicyUri);
+ securityPolicy = getSecurityPolicyByUri(server, &ed->securityPolicyUri);
else
- securityPolicy = UA_SecurityPolicy_getSecurityPolicyByUri(server, &utp->securityPolicyUri);
+ securityPolicy = getSecurityPolicyByUri(server, &utp->securityPolicyUri);
if(!securityPolicy) {
response->responseHeader.serviceResult = UA_STATUSCODE_BADINTERNALERROR;
- goto rejected;
+ goto securityRejected;
}
/* Test if the encryption algorithm is correctly specified */
@@ -34660,21 +37344,22 @@ Service_ActivateSession(UA_Server *server, UA_SecureChannel *channel,
* used for the password from the SecureChannel */
void *tempChannelContext = channel->channelContext;
if(securityPolicy != channel->securityPolicy) {
- /* TODO: This is a hack. We use our own certificate to create a
- * channel context. Because the client does not provide one in a
- * #None SecureChannel. We should not need a ChannelContext at all
- * for asymmetric decryption where the remote certificate is not
+ /* We use our own certificate to create a temporary channel
+ * context. Because the client does not provide one in a #None
+ * SecureChannel. We should not need a ChannelContext at all for
+ * asymmetric decryption where the remote certificate is not
* used. */
- response->responseHeader.serviceResult =
- securityPolicy->channelModule.
+ UA_UNLOCK(&server->serviceMutex);
+ response->responseHeader.serviceResult = securityPolicy->channelModule.
newContext(securityPolicy, &securityPolicy->localCertificate,
&tempChannelContext);
+ UA_LOCK(&server->serviceMutex);
if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
UA_LOG_WARNING_SESSION(&server->config.logger, session, "ActivateSession: "
"Failed to create a context for the SecurityPolicy %.*s",
(int)securityPolicy->policyUri.length,
securityPolicy->policyUri.data);
- goto rejected;
+ goto securityRejected;
}
}
@@ -34683,8 +37368,15 @@ Service_ActivateSession(UA_Server *server, UA_SecureChannel *channel,
decryptPassword(securityPolicy, tempChannelContext, &session->serverNonce, userToken);
/* Remove the temporary channel context */
- if(securityPolicy != channel->securityPolicy)
+ if(securityPolicy != channel->securityPolicy) {
+ UA_UNLOCK(&server->serviceMutex);
securityPolicy->channelModule.deleteContext(tempChannelContext);
+ UA_LOCK(&server->serviceMutex);
+ }
+ } else if(userToken->encryptionAlgorithm.length != 0) {
+ /* If SecurityPolicy is None there shall be no EncryptionAlgorithm */
+ response->responseHeader.serviceResult = UA_STATUSCODE_BADIDENTITYTOKENINVALID;
+ goto securityRejected;
}
if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
@@ -34696,16 +37388,72 @@ Service_ActivateSession(UA_Server *server, UA_SecureChannel *channel,
#endif
}
+#ifdef UA_ENABLE_ENCRYPTION
+ /* If it is a X509IdentityToken, check the userTokenSignature. Note this
+ * only validates that the user has the corresponding private key for the
+ * given user cetificate. Checking whether the user certificate is trusted
+ * has to be implemented in the access control plugin. The entire token is
+ * forwarded in the call to ActivateSession. */
+ if(utp->tokenType == UA_USERTOKENTYPE_CERTIFICATE) {
+ UA_X509IdentityToken* userCertToken = (UA_X509IdentityToken*)
+ request->userIdentityToken.content.decoded.data;
+
+ /* If the userTokenPolicy doesn't specify a security policy the security
+ * policy of the secure channel is used. */
+ UA_SecurityPolicy* securityPolicy;
+ if(!utp->securityPolicyUri.data)
+ securityPolicy = getSecurityPolicyByUri(server, &ed->securityPolicyUri);
+ else
+ securityPolicy = getSecurityPolicyByUri(server, &utp->securityPolicyUri);
+ if(!securityPolicy) {
+ response->responseHeader.serviceResult = UA_STATUSCODE_BADINTERNALERROR;
+ goto securityRejected;
+ }
+
+ /* We need a channel context with the user certificate in order to reuse
+ * the signature checking code. */
+ void *tempChannelContext;
+ UA_UNLOCK(&server->serviceMutex);
+ response->responseHeader.serviceResult = securityPolicy->channelModule.
+ newContext(securityPolicy, &userCertToken->certificateData, &tempChannelContext);
+ UA_LOCK(&server->serviceMutex);
+ if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
+ UA_LOG_WARNING_SESSION(&server->config.logger, session, "ActivateSession: "
+ "Failed to create a context for the SecurityPolicy %.*s",
+ (int)securityPolicy->policyUri.length,
+ securityPolicy->policyUri.data);
+ goto securityRejected;
+ }
+
+ /* Check the user token signature */
+ response->responseHeader.serviceResult =
+ checkSignature(server, channel->securityPolicy, tempChannelContext,
+ &session->serverNonce, &request->userTokenSignature);
+
+ /* Delete the temporary channel context */
+ UA_UNLOCK(&server->serviceMutex);
+ securityPolicy->channelModule.deleteContext(tempChannelContext);
+ UA_LOCK(&server->serviceMutex);
+ if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
+ UA_LOG_WARNING_SESSION(&server->config.logger, session,
+ "ActivateSession: User token signature check failed with StatusCode %s",
+ UA_StatusCode_name(response->responseHeader.serviceResult));
+ goto securityRejected;
+ }
+ }
+#endif
+
/* Callback into userland access control */
- response->responseHeader.serviceResult =
- server->config.accessControl.
+ UA_UNLOCK(&server->serviceMutex);
+ response->responseHeader.serviceResult = server->config.accessControl.
activateSession(server, &server->config.accessControl, ed, &channel->remoteCertificate,
&session->sessionId, &request->userIdentityToken, &session->sessionHandle);
+ UA_LOCK(&server->serviceMutex);
if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
UA_LOG_WARNING_SESSION(&server->config.logger, session, "ActivateSession: The AccessControl "
"plugin denied the activation with the StatusCode %s",
UA_StatusCode_name(response->responseHeader.serviceResult));
- goto rejected;
+ goto securityRejected;
}
/* Attach the session to the currently used channel if the session isn't
@@ -34729,29 +37477,65 @@ Service_ActivateSession(UA_Server *server, UA_SecureChannel *channel,
goto rejected;
}
+ /* Set the locale */
+ response->responseHeader.serviceResult |=
+ UA_Array_copy(request->localeIds, request->localeIdsSize,
+ (void**)&tmpLocaleIds, &UA_TYPES[UA_TYPES_STRING]);
+ if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
+ UA_Session_detachFromSecureChannel(session);
+ UA_LOG_WARNING_SESSION(&server->config.logger, session,
+ "ActivateSession: Could not store the Session LocaleIds");
+ goto rejected;
+ }
+ UA_Array_delete(session->localeIds, session->localeIdsSize,
+ &UA_TYPES[UA_TYPES_STRING]);
+ session->localeIds = tmpLocaleIds;
+ session->localeIdsSize = request->localeIdsSize;
+
UA_Session_updateLifetime(session);
/* Activate the session */
if(!session->activated) {
session->activated = true;
- UA_atomic_addSize(&server->serverStats.ss.currentSessionCount, 1);
- UA_atomic_addSize(&server->serverStats.ss.cumulatedSessionCount, 1);
+ server->activeSessionCount++;
+ server->serverDiagnosticsSummary.cumulatedSessionCount++;
}
+#ifdef UA_ENABLE_DIAGNOSTICS
+ saveClientUserId(&request->userIdentityToken,
+ &session->securityDiagnostics);
+ UA_String_clear(&session->securityDiagnostics.authenticationMechanism);
+ switch(utp->tokenType) {
+ case UA_USERTOKENTYPE_ANONYMOUS:
+ session->securityDiagnostics.authenticationMechanism = UA_STRING_ALLOC("Anonymous");
+ break;
+ case UA_USERTOKENTYPE_USERNAME:
+ session->securityDiagnostics.authenticationMechanism = UA_STRING_ALLOC("UserName");
+ break;
+ case UA_USERTOKENTYPE_CERTIFICATE:
+ session->securityDiagnostics.authenticationMechanism = UA_STRING_ALLOC("Certificate");
+ break;
+ case UA_USERTOKENTYPE_ISSUEDTOKEN:
+ session->securityDiagnostics.authenticationMechanism = UA_STRING_ALLOC("IssuedToken");
+ break;
+ default: break;
+ }
+#endif
+
UA_LOG_INFO_SESSION(&server->config.logger, session, "ActivateSession: Session activated");
return;
securityRejected:
- UA_atomic_addSize(&server->serverStats.ss.securityRejectedSessionCount, 1);
+ server->serverDiagnosticsSummary.securityRejectedSessionCount++;
rejected:
- UA_atomic_addSize(&server->serverStats.ss.rejectedSessionCount, 1);
+ server->serverDiagnosticsSummary.rejectedSessionCount++;
}
void
Service_CloseSession(UA_Server *server, UA_SecureChannel *channel,
const UA_CloseSessionRequest *request,
UA_CloseSessionResponse *response) {
- UA_LOCK_ASSERT(server->serviceMutex, 1);
+ UA_LOCK_ASSERT(&server->serviceMutex, 1);
/* Part 4, 5.6.4: When the CloseSession Service is called before the Session
* is successfully activated, the Server shall reject the request if the
@@ -34771,13 +37555,28 @@ Service_CloseSession(UA_Server *server, UA_SecureChannel *channel,
return;
}
- UA_LOG_INFO_SESSION(&server->config.logger, session, "CloseSession");
+ UA_assert(session); /* Assured by the previous section */
+ UA_LOG_INFO_SESSION(&server->config.logger, session, "Closing the Session");
+
+#ifdef UA_ENABLE_SUBSCRIPTIONS
+ /* If Subscriptions are not deleted, detach them from the Session */
+ if(!request->deleteSubscriptions) {
+ UA_Subscription *sub, *sub_tmp;
+ TAILQ_FOREACH_SAFE(sub, &session->subscriptions, sessionListEntry, sub_tmp) {
+ UA_LOG_INFO_SUBSCRIPTION(&server->config.logger, sub,
+ "Detaching the Subscription from the Session");
+ UA_Session_detachSubscription(server, session, sub, true);
+ }
+ }
+#endif
+
+ /* Remove the sesison */
response->responseHeader.serviceResult =
UA_Server_removeSessionByToken(server, &session->header.authenticationToken,
UA_DIAGNOSTICEVENT_CLOSE);
}
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/src/server/ua_services_attribute.c" ***********************************/
+/**** amalgamated original file "/src/server/ua_services_attribute.c" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -34797,6 +37596,7 @@ Service_CloseSession(UA_Server *server, UA_SecureChannel *channel,
* Copyright 2017 (c) Julian Grothoff
* Copyright 2017-2020 (c) HMS Industrial Networks AB (Author: Jonas Green)
* Copyright 2017 (c) Henrik Norrman
+ * Copyright 2020 (c) Christian von Arnim, ISW University of Stuttgart (for VDW and umati)
*/
@@ -34807,18 +37607,23 @@ Service_CloseSession(UA_Server *server, UA_SecureChannel *channel,
/* Access Control */
/******************/
+/* Session for read operations can be NULL. For example for a MonitoredItem
+ * where the underlying Subscription was detached during CloseSession. */
+
static UA_UInt32
getUserWriteMask(UA_Server *server, const UA_Session *session,
- const UA_Node *node) {
+ const UA_NodeHead *head) {
if(session == &server->adminSession)
return 0xFFFFFFFF; /* the local admin user has all rights */
- UA_UInt32 retval = node->writeMask;
- UA_UNLOCK(server->serviceMutex);
- retval &= server->config.accessControl.getUserRightsMask(server, &server->config.accessControl,
- &session->sessionId, session->sessionHandle,
- &node->nodeId, node->context);
- UA_LOCK(server->serviceMutex);
- return retval;
+ UA_UInt32 mask = head->writeMask;
+ UA_UNLOCK(&server->serviceMutex);
+ mask &= server->config.accessControl.
+ getUserRightsMask(server, &server->config.accessControl,
+ session ? &session->sessionId : NULL,
+ session ? session->sessionHandle : NULL,
+ &head->nodeId, head->context);
+ UA_LOCK(&server->serviceMutex);
+ return mask;
}
static UA_Byte
@@ -34835,11 +37640,13 @@ getUserAccessLevel(UA_Server *server, const UA_Session *session,
if(session == &server->adminSession)
return 0xFF; /* the local admin user has all rights */
UA_Byte retval = node->accessLevel;
- UA_UNLOCK(server->serviceMutex);
- retval &= server->config.accessControl.getUserAccessLevel(server, &server->config.accessControl,
- &session->sessionId, session->sessionHandle,
- &node->nodeId, node->context);
- UA_LOCK(server->serviceMutex);
+ UA_UNLOCK(&server->serviceMutex);
+ retval &= server->config.accessControl.
+ getUserAccessLevel(server, &server->config.accessControl,
+ session ? &session->sessionId : NULL,
+ session ? session->sessionHandle : NULL,
+ &node->head.nodeId, node->head.context);
+ UA_LOCK(&server->serviceMutex);
return retval;
}
@@ -34848,13 +37655,16 @@ getUserExecutable(UA_Server *server, const UA_Session *session,
const UA_MethodNode *node) {
if(session == &server->adminSession)
return true; /* the local admin user has all rights */
- UA_Boolean retval = node->executable;
- UA_UNLOCK(server->serviceMutex);
- retval &= server->config.accessControl.getUserExecutable(server, &server->config.accessControl,
- &session->sessionId, session->sessionHandle,
- &node->nodeId, node->context);
- UA_LOCK(server->serviceMutex);
- return retval;
+ UA_UNLOCK(&server->serviceMutex);
+ UA_Boolean userExecutable = node->executable;
+ userExecutable &=
+ server->config.accessControl.
+ getUserExecutable(server, &server->config.accessControl,
+ session ? &session->sessionId : NULL,
+ session ? session->sessionHandle : NULL,
+ &node->head.nodeId, node->head.context);
+ UA_LOCK(&server->serviceMutex);
+ return userExecutable;
}
/****************/
@@ -34864,18 +37674,18 @@ getUserExecutable(UA_Server *server, const UA_Session *session,
static UA_StatusCode
readIsAbstractAttribute(const UA_Node *node, UA_Variant *v) {
const UA_Boolean *isAbstract;
- switch(node->nodeClass) {
+ switch(node->head.nodeClass) {
case UA_NODECLASS_REFERENCETYPE:
- isAbstract = &((const UA_ReferenceTypeNode*)node)->isAbstract;
+ isAbstract = &node->referenceTypeNode.isAbstract;
break;
case UA_NODECLASS_OBJECTTYPE:
- isAbstract = &((const UA_ObjectTypeNode*)node)->isAbstract;
+ isAbstract = &node->objectTypeNode.isAbstract;
break;
case UA_NODECLASS_VARIABLETYPE:
- isAbstract = &((const UA_VariableTypeNode*)node)->isAbstract;
+ isAbstract = &node->variableTypeNode.isAbstract;
break;
case UA_NODECLASS_DATATYPE:
- isAbstract = &((const UA_DataTypeNode*)node)->isAbstract;
+ isAbstract = &node->dataTypeNode.isAbstract;
break;
default:
return UA_STATUSCODE_BADATTRIBUTEIDINVALID;
@@ -34890,12 +37700,14 @@ readValueAttributeFromNode(UA_Server *server, UA_Session *session,
UA_NumericRange *rangeptr) {
/* Update the value by the user callback */
if(vn->value.data.callback.onRead) {
- UA_UNLOCK(server->serviceMutex);
- vn->value.data.callback.onRead(server, &session->sessionId,
- session->sessionHandle, &vn->nodeId,
- vn->context, rangeptr, &vn->value.data.value);
- UA_LOCK(server->serviceMutex);
- vn = (const UA_VariableNode*)UA_NODESTORE_GET(server, &vn->nodeId);
+ UA_UNLOCK(&server->serviceMutex);
+ vn->value.data.callback.onRead(server,
+ session ? &session->sessionId : NULL,
+ session ? session->sessionHandle : NULL,
+ &vn->head.nodeId, vn->head.context, rangeptr,
+ &vn->value.data.value);
+ UA_LOCK(&server->serviceMutex);
+ vn = (const UA_VariableNode*)UA_NODESTORE_GET(server, &vn->head.nodeId);
if(!vn)
return UA_STATUSCODE_BADNODEIDUNKNOWN;
}
@@ -34922,11 +37734,14 @@ readValueAttributeFromDataSource(UA_Server *server, UA_Session *session,
timestamps == UA_TIMESTAMPSTORETURN_BOTH);
UA_DataValue v2;
UA_DataValue_init(&v2);
- UA_UNLOCK(server->serviceMutex);
+ UA_UNLOCK(&server->serviceMutex);
UA_StatusCode retval = vn->value.dataSource.
- read(server, &session->sessionId, session->sessionHandle,
- &vn->nodeId, vn->context, sourceTimeStamp, rangeptr, &v2);
- UA_LOCK(server->serviceMutex);
+ read(server,
+ session ? &session->sessionId : NULL,
+ session ? session->sessionHandle : NULL,
+ &vn->head.nodeId, vn->head.context,
+ sourceTimeStamp, rangeptr, &v2);
+ UA_LOCK(&server->serviceMutex);
if(v2.hasValue && v2.value.storageType == UA_VARIANT_DATA_NODELETE) {
retval = UA_DataValue_copy(&v2, v);
UA_DataValue_clear(&v2);
@@ -34951,11 +37766,58 @@ readValueAttributeComplete(UA_Server *server, UA_Session *session,
rangeptr = &range;
}
- /* Read the value */
- if(vn->valueSource == UA_VALUESOURCE_DATA)
- retval = readValueAttributeFromNode(server, session, vn, v, rangeptr);
- else
- retval = readValueAttributeFromDataSource(server, session, vn, v, timestamps, rangeptr);
+ switch(vn->valueBackend.backendType) {
+ case UA_VALUEBACKENDTYPE_INTERNAL:
+ retval = readValueAttributeFromNode(server, session, vn, v, rangeptr);
+ //TODO change old structure to value backend
+ break;
+ case UA_VALUEBACKENDTYPE_DATA_SOURCE_CALLBACK:
+ retval = readValueAttributeFromDataSource(server, session, vn, v,
+ timestamps, rangeptr);
+ //TODO change old structure to value backend
+ break;
+ case UA_VALUEBACKENDTYPE_EXTERNAL:
+ if(vn->valueBackend.backend.external.callback.notificationRead){
+ retval = vn->valueBackend.backend.external.callback.
+ notificationRead(server,
+ session ? &session->sessionId : NULL,
+ session ? session->sessionHandle : NULL,
+ &vn->head.nodeId, vn->head.context, rangeptr);
+ } else {
+ retval = UA_STATUSCODE_BADNOTREADABLE;
+ }
+ if(retval != UA_STATUSCODE_GOOD){
+ break;
+ }
+ /* Set the result */
+ if(rangeptr)
+ retval = UA_DataValue_copyVariantRange(
+ *vn->valueBackend.backend.external.value, v, *rangeptr);
+ else
+ retval = UA_DataValue_copy(*vn->valueBackend.backend.external.value, v);
+ break;
+ case UA_VALUEBACKENDTYPE_NONE:
+ /* Read the value */
+ if(vn->valueSource == UA_VALUESOURCE_DATA)
+ retval = readValueAttributeFromNode(server, session, vn, v, rangeptr);
+ else
+ retval = readValueAttributeFromDataSource(server, session, vn, v,
+ timestamps, rangeptr);
+ /* end lagacy */
+ break;
+ }
+
+ /* Static Variables and VariableTypes have timestamps of "now". Will be set
+ * below in the absence of predefined timestamps. */
+ if(vn->head.nodeClass == UA_NODECLASS_VARIABLE) {
+ if(!vn->isDynamic) {
+ v->hasServerTimestamp = false;
+ v->hasSourceTimestamp = false;
+ }
+ } else {
+ v->hasServerTimestamp = false;
+ v->hasSourceTimestamp = false;
+ }
/* Clean up */
if(rangeptr)
@@ -34966,7 +37828,8 @@ readValueAttributeComplete(UA_Server *server, UA_Session *session,
UA_StatusCode
readValueAttribute(UA_Server *server, UA_Session *session,
const UA_VariableNode *vn, UA_DataValue *v) {
- return readValueAttributeComplete(server, session, vn, UA_TIMESTAMPSTORETURN_NEITHER, NULL, v);
+ return readValueAttributeComplete(server, session, vn,
+ UA_TIMESTAMPSTORETURN_NEITHER, NULL, v);
}
static const UA_String binEncoding = {sizeof("Default Binary")-1, (UA_Byte*)"Default Binary"};
@@ -34974,7 +37837,7 @@ static const UA_String xmlEncoding = {sizeof("Default XML")-1, (UA_Byte*)"Defaul
static const UA_String jsonEncoding = {sizeof("Default JSON")-1, (UA_Byte*)"Default JSON"};
#define CHECK_NODECLASS(CLASS) \
- if(!(node->nodeClass & (CLASS))) { \
+ if(!(node->head.nodeClass & (CLASS))) { \
retval = UA_STATUSCODE_BADATTRIBUTEIDINVALID; \
break; \
}
@@ -34983,7 +37846,7 @@ static const UA_String jsonEncoding = {sizeof("Default JSON")-1, (UA_Byte*)"Defa
static const UA_DataType *
findDataType(const UA_Node *node, const UA_DataTypeArray *customTypes) {
for(size_t i = 0; i < UA_TYPES_COUNT; ++i) {
- if(UA_NodeId_equal(&UA_TYPES[i].typeId, &node->nodeId)) {
+ if(UA_NodeId_equal(&UA_TYPES[i].typeId, &node->head.nodeId)) {
return &UA_TYPES[i];
}
}
@@ -34991,7 +37854,7 @@ findDataType(const UA_Node *node, const UA_DataTypeArray *customTypes) {
// lookup custom type
while(customTypes) {
for(size_t i = 0; i < customTypes->typesSize; ++i) {
- if(UA_NodeId_equal(&customTypes->types[i].typeId, &node->nodeId))
+ if(UA_NodeId_equal(&customTypes->types[i].typeId, &node->head.nodeId))
return &customTypes->types[i];
}
customTypes = customTypes->next;
@@ -35001,8 +37864,10 @@ findDataType(const UA_Node *node, const UA_DataTypeArray *customTypes) {
static UA_StatusCode
getStructureDefinition(const UA_DataType *type, UA_StructureDefinition *def) {
- def->defaultEncodingId =
- UA_NODEID_NUMERIC(type->typeId.namespaceIndex, type->binaryEncodingId);
+ UA_StatusCode retval =
+ UA_NodeId_copy(&type->binaryEncodingId, &def->defaultEncodingId);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
switch(type->typeKind) {
case UA_DATATYPEKIND_STRUCTURE:
def->structureType = UA_STRUCTURETYPE_STRUCTURE;
@@ -35020,22 +37885,22 @@ getStructureDefinition(const UA_DataType *type, UA_StructureDefinition *def) {
return UA_STATUSCODE_BADENCODINGERROR;
}
def->fieldsSize = type->membersSize;
- def->fields =
- (UA_StructureField *)UA_calloc(def->fieldsSize, sizeof(UA_StructureField));
+ def->fields = (UA_StructureField *)
+ UA_calloc(def->fieldsSize, sizeof(UA_StructureField));
if(!def->fields) {
+ UA_NodeId_clear(&def->defaultEncodingId);
return UA_STATUSCODE_BADOUTOFMEMORY;
}
- const UA_DataType *typelists[2] = {UA_TYPES, &type[-type->typeIndex]};
+
for(size_t cnt = 0; cnt < def->fieldsSize; cnt++) {
const UA_DataTypeMember *m = &type->members[cnt];
def->fields[cnt].valueRank = UA_TRUE == m->isArray ? 1 : -1;
def->fields[cnt].arrayDimensions = NULL;
def->fields[cnt].arrayDimensionsSize = 0;
- def->fields[cnt].name =
- UA_STRING((char *)(uintptr_t)m->memberName);
+ def->fields[cnt].name = UA_STRING((char *)(uintptr_t)m->memberName);
def->fields[cnt].description.locale = UA_STRING_NULL;
def->fields[cnt].description.text = UA_STRING_NULL;
- def->fields[cnt].dataType = typelists[!m->namespaceZero][m->memberTypeIndex].typeId;
+ def->fields[cnt].dataType = m->memberType->typeId;
def->fields[cnt].maxStringLength = 0;
def->fields[cnt].isOptional = m->isOptional;
}
@@ -35050,8 +37915,11 @@ void
ReadWithNode(const UA_Node *node, UA_Server *server, UA_Session *session,
UA_TimestampsToReturn timestampsToReturn,
const UA_ReadValueId *id, UA_DataValue *v) {
- UA_LOG_DEBUG_SESSION(&server->config.logger, session,
- "Read the attribute %" PRIi32, id->attributeId);
+ UA_LOG_NODEID_DEBUG(&node->head.nodeId,
+ UA_LOG_DEBUG_SESSION(&server->config.logger, session,
+ "Read attribute %"PRIi32 " of Node %.*s",
+ id->attributeId, (int)nodeIdStr.length,
+ nodeIdStr.data));
/* Only Binary Encoding is supported */
if(id->dataEncoding.name.length > 0 &&
@@ -35076,129 +37944,140 @@ ReadWithNode(const UA_Node *node, UA_Server *server, UA_Session *session,
UA_StatusCode retval = UA_STATUSCODE_GOOD;
switch(id->attributeId) {
case UA_ATTRIBUTEID_NODEID:
- retval = UA_Variant_setScalarCopy(&v->value, &node->nodeId, &UA_TYPES[UA_TYPES_NODEID]);
+ retval = UA_Variant_setScalarCopy(&v->value, &node->head.nodeId,
+ &UA_TYPES[UA_TYPES_NODEID]);
break;
case UA_ATTRIBUTEID_NODECLASS:
- retval = UA_Variant_setScalarCopy(&v->value, &node->nodeClass, &UA_TYPES[UA_TYPES_NODECLASS]);
+ retval = UA_Variant_setScalarCopy(&v->value, &node->head.nodeClass,
+ &UA_TYPES[UA_TYPES_NODECLASS]);
break;
case UA_ATTRIBUTEID_BROWSENAME:
- retval = UA_Variant_setScalarCopy(&v->value, &node->browseName, &UA_TYPES[UA_TYPES_QUALIFIEDNAME]);
+ retval = UA_Variant_setScalarCopy(&v->value, &node->head.browseName,
+ &UA_TYPES[UA_TYPES_QUALIFIEDNAME]);
break;
case UA_ATTRIBUTEID_DISPLAYNAME:
- retval = UA_Variant_setScalarCopy(&v->value, &node->displayName, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]);
+ retval = UA_Variant_setScalarCopy(&v->value, &node->head.displayName,
+ &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]);
break;
case UA_ATTRIBUTEID_DESCRIPTION:
- retval = UA_Variant_setScalarCopy(&v->value, &node->description, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]);
+ retval = UA_Variant_setScalarCopy(&v->value, &node->head.description,
+ &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]);
break;
case UA_ATTRIBUTEID_WRITEMASK:
- retval = UA_Variant_setScalarCopy(&v->value, &node->writeMask, &UA_TYPES[UA_TYPES_UINT32]);
+ retval = UA_Variant_setScalarCopy(&v->value, &node->head.writeMask,
+ &UA_TYPES[UA_TYPES_UINT32]);
break;
case UA_ATTRIBUTEID_USERWRITEMASK: {
- UA_UInt32 userWriteMask = getUserWriteMask(server, session, node);
- retval = UA_Variant_setScalarCopy(&v->value, &userWriteMask, &UA_TYPES[UA_TYPES_UINT32]);
+ UA_UInt32 userWriteMask = getUserWriteMask(server, session, &node->head);
+ retval = UA_Variant_setScalarCopy(&v->value, &userWriteMask,
+ &UA_TYPES[UA_TYPES_UINT32]);
break; }
case UA_ATTRIBUTEID_ISABSTRACT:
retval = readIsAbstractAttribute(node, &v->value);
break;
case UA_ATTRIBUTEID_SYMMETRIC:
CHECK_NODECLASS(UA_NODECLASS_REFERENCETYPE);
- retval = UA_Variant_setScalarCopy(&v->value, &((const UA_ReferenceTypeNode*)node)->symmetric,
- &UA_TYPES[UA_TYPES_BOOLEAN]);
+ retval = UA_Variant_setScalarCopy(&v->value, &node->referenceTypeNode.symmetric,
+ &UA_TYPES[UA_TYPES_BOOLEAN]);
break;
case UA_ATTRIBUTEID_INVERSENAME:
CHECK_NODECLASS(UA_NODECLASS_REFERENCETYPE);
- retval = UA_Variant_setScalarCopy(&v->value, &((const UA_ReferenceTypeNode*)node)->inverseName,
- &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]);
+ retval = UA_Variant_setScalarCopy(&v->value, &node->referenceTypeNode.inverseName,
+ &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]);
break;
case UA_ATTRIBUTEID_CONTAINSNOLOOPS:
CHECK_NODECLASS(UA_NODECLASS_VIEW);
- retval = UA_Variant_setScalarCopy(&v->value, &((const UA_ViewNode*)node)->containsNoLoops,
- &UA_TYPES[UA_TYPES_BOOLEAN]);
+ retval = UA_Variant_setScalarCopy(&v->value, &node->viewNode.containsNoLoops,
+ &UA_TYPES[UA_TYPES_BOOLEAN]);
break;
case UA_ATTRIBUTEID_EVENTNOTIFIER:
CHECK_NODECLASS(UA_NODECLASS_VIEW | UA_NODECLASS_OBJECT);
- if(node->nodeClass == UA_NODECLASS_VIEW) {
- retval = UA_Variant_setScalarCopy(&v->value, &((const UA_ViewNode*)node)->eventNotifier,
- &UA_TYPES[UA_TYPES_BYTE]);
- }
- else{
- retval = UA_Variant_setScalarCopy(&v->value, &((const UA_ObjectNode*)node)->eventNotifier,
- &UA_TYPES[UA_TYPES_BYTE]);
+ if(node->head.nodeClass == UA_NODECLASS_VIEW) {
+ retval = UA_Variant_setScalarCopy(&v->value, &node->viewNode.eventNotifier,
+ &UA_TYPES[UA_TYPES_BYTE]);
+ } else {
+ retval = UA_Variant_setScalarCopy(&v->value, &node->objectNode.eventNotifier,
+ &UA_TYPES[UA_TYPES_BYTE]);
}
break;
case UA_ATTRIBUTEID_VALUE: {
CHECK_NODECLASS(UA_NODECLASS_VARIABLE | UA_NODECLASS_VARIABLETYPE);
- /* VariableTypes don't have the AccessLevel concept. Always allow reading the value. */
- if(node->nodeClass == UA_NODECLASS_VARIABLE) {
+ /* VariableTypes don't have the AccessLevel concept. Always allow
+ * reading the value. */
+ if(node->head.nodeClass == UA_NODECLASS_VARIABLE) {
/* The access to a value variable is granted via the AccessLevel
* and UserAccessLevel attributes */
- UA_Byte accessLevel = getAccessLevel(server, session, (const UA_VariableNode*)node);
+ UA_Byte accessLevel = getAccessLevel(server, session, &node->variableNode);
if(!(accessLevel & (UA_ACCESSLEVELMASK_READ))) {
retval = UA_STATUSCODE_BADNOTREADABLE;
break;
}
- accessLevel = getUserAccessLevel(server, session,
- (const UA_VariableNode*)node);
+ accessLevel = getUserAccessLevel(server, session, &node->variableNode);
if(!(accessLevel & (UA_ACCESSLEVELMASK_READ))) {
retval = UA_STATUSCODE_BADUSERACCESSDENIED;
break;
}
}
- retval = readValueAttributeComplete(server, session, (const UA_VariableNode*)node,
+ retval = readValueAttributeComplete(server, session, &node->variableNode,
timestampsToReturn, &id->indexRange, v);
break;
}
case UA_ATTRIBUTEID_DATATYPE:
CHECK_NODECLASS(UA_NODECLASS_VARIABLE | UA_NODECLASS_VARIABLETYPE);
- retval = UA_Variant_setScalarCopy(&v->value, &((const UA_VariableTypeNode*)node)->dataType,
+ retval = UA_Variant_setScalarCopy(&v->value, &node->variableTypeNode.dataType,
&UA_TYPES[UA_TYPES_NODEID]);
break;
case UA_ATTRIBUTEID_VALUERANK:
CHECK_NODECLASS(UA_NODECLASS_VARIABLE | UA_NODECLASS_VARIABLETYPE);
- retval = UA_Variant_setScalarCopy(&v->value, &((const UA_VariableTypeNode*)node)->valueRank,
+ retval = UA_Variant_setScalarCopy(&v->value, &node->variableTypeNode.valueRank,
&UA_TYPES[UA_TYPES_INT32]);
break;
case UA_ATTRIBUTEID_ARRAYDIMENSIONS:
CHECK_NODECLASS(UA_NODECLASS_VARIABLE | UA_NODECLASS_VARIABLETYPE);
- retval = UA_Variant_setArrayCopy(&v->value, ((const UA_VariableTypeNode*)node)->arrayDimensions,
- ((const UA_VariableTypeNode*)node)->arrayDimensionsSize,
+ retval = UA_Variant_setArrayCopy(&v->value, node->variableTypeNode.arrayDimensions,
+ node->variableTypeNode.arrayDimensionsSize,
&UA_TYPES[UA_TYPES_UINT32]);
break;
case UA_ATTRIBUTEID_ACCESSLEVEL:
CHECK_NODECLASS(UA_NODECLASS_VARIABLE);
- retval = UA_Variant_setScalarCopy(&v->value, &((const UA_VariableNode*)node)->accessLevel,
+ retval = UA_Variant_setScalarCopy(&v->value, &node->variableNode.accessLevel,
&UA_TYPES[UA_TYPES_BYTE]);
break;
case UA_ATTRIBUTEID_USERACCESSLEVEL: {
CHECK_NODECLASS(UA_NODECLASS_VARIABLE);
- UA_Byte userAccessLevel = getUserAccessLevel(server, session, (const UA_VariableNode*)node);
- retval = UA_Variant_setScalarCopy(&v->value, &userAccessLevel, &UA_TYPES[UA_TYPES_BYTE]);
+ UA_Byte userAccessLevel = getUserAccessLevel(server, session, &node->variableNode);
+ retval = UA_Variant_setScalarCopy(&v->value, &userAccessLevel,
+ &UA_TYPES[UA_TYPES_BYTE]);
break; }
case UA_ATTRIBUTEID_MINIMUMSAMPLINGINTERVAL:
CHECK_NODECLASS(UA_NODECLASS_VARIABLE);
- retval = UA_Variant_setScalarCopy(&v->value, &((const UA_VariableNode*)node)->minimumSamplingInterval,
- &UA_TYPES[UA_TYPES_DOUBLE]);
+ retval = UA_Variant_setScalarCopy(&v->value,
+ &node->variableNode.minimumSamplingInterval,
+ &UA_TYPES[UA_TYPES_DOUBLE]);
break;
case UA_ATTRIBUTEID_HISTORIZING:
CHECK_NODECLASS(UA_NODECLASS_VARIABLE);
- retval = UA_Variant_setScalarCopy(&v->value, &((const UA_VariableNode*)node)->historizing,
- &UA_TYPES[UA_TYPES_BOOLEAN]);
+ retval = UA_Variant_setScalarCopy(&v->value, &node->variableNode.historizing,
+ &UA_TYPES[UA_TYPES_BOOLEAN]);
break;
case UA_ATTRIBUTEID_EXECUTABLE:
CHECK_NODECLASS(UA_NODECLASS_METHOD);
- retval = UA_Variant_setScalarCopy(&v->value, &((const UA_MethodNode*)node)->executable,
+ retval = UA_Variant_setScalarCopy(&v->value, &node->methodNode.executable,
&UA_TYPES[UA_TYPES_BOOLEAN]);
break;
case UA_ATTRIBUTEID_USEREXECUTABLE: {
CHECK_NODECLASS(UA_NODECLASS_METHOD);
- UA_Boolean userExecutable = getUserExecutable(server, session, (const UA_MethodNode*)node);
- retval = UA_Variant_setScalarCopy(&v->value, &userExecutable, &UA_TYPES[UA_TYPES_BOOLEAN]);
+ UA_Boolean userExecutable =
+ getUserExecutable(server, session, &node->methodNode);
+ retval = UA_Variant_setScalarCopy(&v->value, &userExecutable,
+ &UA_TYPES[UA_TYPES_BOOLEAN]);
break; }
case UA_ATTRIBUTEID_DATATYPEDEFINITION: {
CHECK_NODECLASS(UA_NODECLASS_DATATYPE);
#ifdef UA_ENABLE_TYPEDESCRIPTION
- const UA_DataType *type = findDataType(node, server->config.customDataTypes);
+ const UA_DataType *type =
+ findDataType(node, server->config.customDataTypes);
if(!type) {
retval = UA_STATUSCODE_BADATTRIBUTEIDINVALID;
break;
@@ -35223,19 +38102,18 @@ ReadWithNode(const UA_Node *node, UA_Server *server, UA_Session *session,
retval = UA_STATUSCODE_BADATTRIBUTEIDINVALID;
}
- /* Return error code when reading has failed */
if(retval != UA_STATUSCODE_GOOD) {
+ /* Reading has failed but can not return because we may need to add timestamp */
v->hasStatus = true;
v->status = retval;
- return;
+ } else {
+ v->hasValue = true;
}
- v->hasValue = true;
-
/* Create server timestamp */
if(timestampsToReturn == UA_TIMESTAMPSTORETURN_SERVER ||
timestampsToReturn == UA_TIMESTAMPSTORETURN_BOTH) {
- if (!v->hasServerTimestamp) {
+ if(!v->hasServerTimestamp) {
v->serverTimestamp = UA_DateTime_now();
v->hasServerTimestamp = true;
}
@@ -35277,7 +38155,7 @@ void
Service_Read(UA_Server *server, UA_Session *session,
const UA_ReadRequest *request, UA_ReadResponse *response) {
UA_LOG_DEBUG_SESSION(&server->config.logger, session, "Processing ReadRequest");
- UA_LOCK_ASSERT(server->serviceMutex, 1);
+ UA_LOCK_ASSERT(&server->serviceMutex, 1);
/* Check if the timestampstoreturn is valid */
if(request->timestampsToReturn > UA_TIMESTAMPSTORETURN_NEITHER) {
@@ -35298,19 +38176,23 @@ Service_Read(UA_Server *server, UA_Session *session,
return;
}
- UA_LOCK_ASSERT(server->serviceMutex, 1);
+ UA_LOCK_ASSERT(&server->serviceMutex, 1);
response->responseHeader.serviceResult =
- UA_Server_processServiceOperations(server, session, (UA_ServiceOperation)Operation_Read,
- request,
- &request->nodesToReadSize, &UA_TYPES[UA_TYPES_READVALUEID],
- &response->resultsSize, &UA_TYPES[UA_TYPES_DATAVALUE]);
+ UA_Server_processServiceOperations(server, session,
+ (UA_ServiceOperation)Operation_Read,
+ request, &request->nodesToReadSize,
+ &UA_TYPES[UA_TYPES_READVALUEID],
+ &response->resultsSize,
+ &UA_TYPES[UA_TYPES_DATAVALUE]);
}
UA_DataValue
UA_Server_readWithSession(UA_Server *server, UA_Session *session,
const UA_ReadValueId *item,
UA_TimestampsToReturn timestampsToReturn) {
+ UA_LOCK_ASSERT(&server->serviceMutex, 1);
+
UA_DataValue dv;
UA_DataValue_init(&dv);
@@ -35333,14 +38215,14 @@ UA_Server_readWithSession(UA_Server *server, UA_Session *session,
UA_DataValue
readAttribute(UA_Server *server, const UA_ReadValueId *item,
UA_TimestampsToReturn timestamps) {
- UA_LOCK_ASSERT(server->serviceMutex, 1);
+ UA_LOCK_ASSERT(&server->serviceMutex, 1);
return UA_Server_readWithSession(server, &server->adminSession, item, timestamps);
}
UA_StatusCode
readWithReadValue(UA_Server *server, const UA_NodeId *nodeId,
- const UA_AttributeId attributeId, void *v) {
- UA_LOCK_ASSERT(server->serviceMutex, 1);
+ const UA_AttributeId attributeId, void *v) {
+ UA_LOCK_ASSERT(&server->serviceMutex, 1);
/* Call the read service */
UA_ReadValueId item;
@@ -35376,9 +38258,9 @@ readWithReadValue(UA_Server *server, const UA_NodeId *nodeId,
UA_DataValue
UA_Server_read(UA_Server *server, const UA_ReadValueId *item,
UA_TimestampsToReturn timestamps) {
- UA_LOCK(server->serviceMutex);
+ UA_LOCK(&server->serviceMutex);
UA_DataValue dv = readAttribute(server, item, timestamps);
- UA_UNLOCK(server->serviceMutex);
+ UA_UNLOCK(&server->serviceMutex);
return dv;
}
@@ -35387,9 +38269,9 @@ UA_Server_read(UA_Server *server, const UA_ReadValueId *item,
UA_StatusCode
__UA_Server_read(UA_Server *server, const UA_NodeId *nodeId,
const UA_AttributeId attributeId, void *v) {
- UA_LOCK(server->serviceMutex);
+ UA_LOCK(&server->serviceMutex);
UA_StatusCode retval = readWithReadValue(server, nodeId, attributeId, v);
- UA_UNLOCK(server->serviceMutex);
+ UA_UNLOCK(&server->serviceMutex);
return retval;
}
@@ -35397,7 +38279,9 @@ UA_StatusCode
readObjectProperty(UA_Server *server, const UA_NodeId objectId,
const UA_QualifiedName propertyName,
UA_Variant *value) {
- UA_LOCK_ASSERT(server->serviceMutex, 1);
+ UA_LOCK_ASSERT(&server->serviceMutex, 1);
+
+ /* Create a BrowsePath to get the target NodeId */
UA_RelativePathElement rpe;
UA_RelativePathElement_init(&rpe);
rpe.referenceTypeId = UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY);
@@ -35419,7 +38303,9 @@ readObjectProperty(UA_Server *server, const UA_NodeId objectId,
return retval;
}
- retval = readWithReadValue(server, &bpr.targets[0].targetId.nodeId, UA_ATTRIBUTEID_VALUE, value);
+ /* Use the first result from the BrowsePath */
+ retval = readWithReadValue(server, &bpr.targets[0].targetId.nodeId,
+ UA_ATTRIBUTEID_VALUE, value);
UA_BrowsePathResult_clear(&bpr);
return retval;
@@ -35430,9 +38316,9 @@ UA_StatusCode
UA_Server_readObjectProperty(UA_Server *server, const UA_NodeId objectId,
const UA_QualifiedName propertyName,
UA_Variant *value) {
- UA_LOCK(server->serviceMutex);
+ UA_LOCK(&server->serviceMutex);
UA_StatusCode retval = readObjectProperty(server, objectId, propertyName, value);
- UA_UNLOCK(server->serviceMutex);
+ UA_UNLOCK(&server->serviceMutex);
return retval;
}
@@ -35451,47 +38337,48 @@ typeEquivalence(const UA_DataType *t) {
static const UA_NodeId enumNodeId = {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_ENUMERATION}};
UA_Boolean
-compatibleDataType(UA_Server *server, const UA_NodeId *dataType,
- const UA_NodeId *constraintDataType, UA_Boolean isValue) {
+compatibleValueDataType(UA_Server *server, const UA_DataType *dataType,
+ const UA_NodeId *constraintDataType) {
+ if(compatibleDataTypes(server, &dataType->typeId, constraintDataType))
+ return true;
+
+ /* For actual values, the constraint DataType may be a subtype of the
+ * DataType of the value. E.g. UtcTime is subtype of DateTime. But it still
+ * is a DateTime value when transferred over the wire. */
+ if(isNodeInTree_singleRef(server, constraintDataType, &dataType->typeId,
+ UA_REFERENCETYPEINDEX_HASSUBTYPE))
+ return true;
+
+ return false;
+}
+
+UA_Boolean
+compatibleDataTypes(UA_Server *server, const UA_NodeId *dataType,
+ const UA_NodeId *constraintDataType) {
/* Do not allow empty datatypes */
if(UA_NodeId_isNull(dataType))
return false;
- /* No constraint (TODO: use variant instead) */
- if(UA_NodeId_isNull(constraintDataType))
+ /* No constraint or Variant / BaseDataType which allows any content */
+ if(UA_NodeId_isNull(constraintDataType) ||
+ UA_NodeId_equal(constraintDataType, &UA_TYPES[UA_TYPES_VARIANT].typeId))
return true;
/* Same datatypes */
- if (UA_NodeId_equal(dataType, constraintDataType))
- return true;
-
- /* Variant allows any subtype */
- if(UA_NodeId_equal(constraintDataType, &UA_TYPES[UA_TYPES_VARIANT].typeId))
+ if(UA_NodeId_equal(dataType, constraintDataType))
return true;
- /* Is the value-type a subtype of the required type? */
- if(isNodeInTree(server, dataType, constraintDataType, &subtypeId, 1))
+ /* Is the DataType a subtype of the constraint type? */
+ if(isNodeInTree_singleRef(server, dataType, constraintDataType,
+ UA_REFERENCETYPEINDEX_HASSUBTYPE))
return true;
- /* Enum allows Int32 (only) */
+ /* The constraint is an enum -> allow writing Int32 */
if(UA_NodeId_equal(dataType, &UA_TYPES[UA_TYPES_INT32].typeId) &&
- isNodeInTree(server, constraintDataType, &enumNodeId, &subtypeId, 1))
+ isNodeInTree_singleRef(server, constraintDataType, &enumNodeId,
+ UA_REFERENCETYPEINDEX_HASSUBTYPE))
return true;
- /* More checks for the data type of real values (variants) */
- if(isValue) {
- /* If value is a built-in type: The target data type may be a sub type of
- * the built-in type. (e.g. UtcTime is sub-type of DateTime and has a
- * DateTime value). A type is builtin if its NodeId is in Namespace 0 and
- * has a numeric identifier <= 25 (DiagnosticInfo) */
- if(dataType->namespaceIndex == 0 &&
- dataType->identifierType == UA_NODEIDTYPE_NUMERIC &&
- dataType->identifier.numeric <= 25 &&
- isNodeInTree(server, constraintDataType,
- dataType, &subtypeId, 1))
- return true;
- }
-
return false;
}
@@ -35510,10 +38397,13 @@ compatibleValueRankArrayDimensions(UA_Server *server, UA_Session *session,
return false;
}
- /* case -3, UA_VALUERANK_SCALAR_OR_ONE_DIMENSION: the value can be a scalar or a one dimensional array */
- /* case -2, UA_VALUERANK_ANY: the value can be a scalar or an array with any number of dimensions */
- /* case -1, UA_VALUERANK_SCALAR: the value is a scalar */
- /* case 0, UA_VALUERANK_ONE_OR_MORE_DIMENSIONS: the value is an array with one or more dimensions */
+ /* case -3, UA_VALUERANK_SCALAR_OR_ONE_DIMENSION: the value can be a scalar
+ * or a one dimensional array
+ * case -2, UA_VALUERANK_ANY: the value can be a scalar or an array with any
+ * number of dimensions
+ * case -1, UA_VALUERANK_SCALAR: the value is a scalar
+ * case 0, UA_VALUERANK_ONE_OR_MORE_DIMENSIONS: the value is an array with
+ * one or more dimensions */
if(valueRank <= UA_VALUERANK_ONE_OR_MORE_DIMENSIONS) {
if(arrayDimensionsSize > 0) {
UA_LOG_INFO_SESSION(&server->config.logger, session,
@@ -35523,10 +38413,12 @@ compatibleValueRankArrayDimensions(UA_Server *server, UA_Session *session,
return true;
}
- /* case >= 1, UA_VALUERANK_ONE_DIMENSION: the value is an array with the specified number of dimensions */
+ /* case >= 1, UA_VALUERANK_ONE_DIMENSION: the value is an array with the
+ specified number of dimensions */
if(arrayDimensionsSize != (size_t)valueRank) {
UA_LOG_INFO_SESSION(&server->config.logger, session,
- "The number of ArrayDimensions is not equal to the (positive) ValueRank");
+ "The number of ArrayDimensions is not equal to "
+ "the (positive) ValueRank");
return false;
}
return true;
@@ -35536,21 +38428,25 @@ UA_Boolean
compatibleValueRanks(UA_Int32 valueRank, UA_Int32 constraintValueRank) {
/* Check if the valuerank of the variabletype allows the change. */
switch(constraintValueRank) {
- case UA_VALUERANK_SCALAR_OR_ONE_DIMENSION: /* the value can be a scalar or a one dimensional array */
+ case UA_VALUERANK_SCALAR_OR_ONE_DIMENSION: /* the value can be a scalar or a
+ one dimensional array */
if(valueRank != UA_VALUERANK_SCALAR && valueRank != UA_VALUERANK_ONE_DIMENSION)
return false;
break;
- case UA_VALUERANK_ANY: /* the value can be a scalar or an array with any number of dimensions */
+ case UA_VALUERANK_ANY: /* the value can be a scalar or an array with any
+ number of dimensions */
break;
case UA_VALUERANK_SCALAR: /* the value is a scalar */
if(valueRank != UA_VALUERANK_SCALAR)
return false;
break;
- case UA_VALUERANK_ONE_OR_MORE_DIMENSIONS: /* the value is an array with one or more dimensions */
+ case UA_VALUERANK_ONE_OR_MORE_DIMENSIONS: /* the value is an array with one
+ or more dimensions */
if(valueRank < (UA_Int32) UA_VALUERANK_ONE_OR_MORE_DIMENSIONS)
return false;
break;
- default: /* >= 1: the value is an array with the specified number of dimensions */
+ default: /* >= 1: the value is an array with the specified number of
+ dimensions */
if(valueRank != constraintValueRank)
return false;
break;
@@ -35578,9 +38474,11 @@ compatibleValueRankValue(UA_Int32 valueRank, const UA_Variant *value) {
/* We cannot simply use compatibleValueRankArrayDimensions since we can have
* defined ArrayDimensions for the value if the ValueRank is -2 */
switch(valueRank) {
- case UA_VALUERANK_SCALAR_OR_ONE_DIMENSION: /* The value can be a scalar or a one dimensional array */
+ case UA_VALUERANK_SCALAR_OR_ONE_DIMENSION: /* The value can be a scalar or a
+ one dimensional array */
return (arrayDims <= 1);
- case UA_VALUERANK_ANY: /* The value can be a scalar or an array with any number of dimensions */
+ case UA_VALUERANK_ANY: /* The value can be a scalar or an array with any
+ number of dimensions */
return true;
case UA_VALUERANK_SCALAR: /* The value is a scalar */
return (arrayDims == 0);
@@ -35635,11 +38533,16 @@ compatibleValueArrayDimensions(const UA_Variant *value, size_t targetArrayDimens
valueArrayDimensionsSize, valueArrayDimensions);
}
+const char *reason_EmptyType = "Empty value only allowed for BaseDataType";
+const char *reason_ValueDataType = "DataType of the value is incompatible";
+const char *reason_ValueArrayDimensions = "ArrayDimensions of the value are incompatible";
+const char *reason_ValueValueRank = "ValueRank of the value is incompatible";
+
UA_Boolean
compatibleValue(UA_Server *server, UA_Session *session, const UA_NodeId *targetDataTypeId,
UA_Int32 targetValueRank, size_t targetArrayDimensionsSize,
const UA_UInt32 *targetArrayDimensions, const UA_Variant *value,
- const UA_NumericRange *range) {
+ const UA_NumericRange *range, const char **reason) {
/* Empty value */
if(!value->type) {
/* Empty value is allowed for BaseDataType */
@@ -35647,45 +38550,61 @@ compatibleValue(UA_Server *server, UA_Session *session, const UA_NodeId *targetD
UA_NodeId_equal(targetDataTypeId, &UA_NODEID_NULL))
return true;
- /* Allow empty node values since existing information models may have
- * variables with no value, e.g. OldValues - ns=0;i=3024. See also
- * #1889, https://github.com/open62541/open62541/pull/1889#issuecomment-403506538 */
- if(server->config.relaxEmptyValueConstraint) {
- UA_LOG_DEBUG_SESSION(&server->config.logger, session,
- "Only Variables with data type BaseDataType can contain an "
- "empty value. Allow via explicit constraint relaxation.");
+ /* Ignore if that is configured */
+ if(server->bootstrapNS0 ||
+ server->config.allowEmptyVariables == UA_RULEHANDLING_ACCEPT)
return true;
- }
UA_LOG_INFO_SESSION(&server->config.logger, session,
- "Only Variables with data type BaseDataType can contain an empty value");
+ "Only Variables with data type BaseDataType "
+ "can contain an empty value");
+
+ /* Ignore if that is configured */
+ if(server->config.allowEmptyVariables == UA_RULEHANDLING_WARN)
+ return true;
+
+ /* Default handling is to abort */
+ *reason = reason_EmptyType;
return false;
}
- /* Has the value a subtype of the required type? BaseDataType (Variant) can
- * be anything... */
- if(!compatibleDataType(server, &value->type->typeId, targetDataTypeId, true))
+ /* Is the datatype compatible? */
+ if(!compatibleValueDataType(server, value->type, targetDataTypeId)) {
+ *reason = reason_ValueDataType;
return false;
+ }
/* Array dimensions are checked later when writing the range */
if(range)
return true;
/* See if the array dimensions match. */
- if(!compatibleValueArrayDimensions(value, targetArrayDimensionsSize, targetArrayDimensions))
+ if(!compatibleValueArrayDimensions(value, targetArrayDimensionsSize,
+ targetArrayDimensions)) {
+ *reason = reason_ValueArrayDimensions;
return false;
+ }
/* Check if the valuerank allows for the value dimension */
- return compatibleValueRankValue(targetValueRank, value);
+ if(!compatibleValueRankValue(targetValueRank, value)) {
+ *reason = reason_ValueValueRank;
+ return false;
+ }
+
+ return true;
}
/*****************/
/* Write Service */
/*****************/
-static void
-adjustValue(UA_Server *server, UA_Variant *value,
- const UA_NodeId *targetDataTypeId) {
+void
+adjustValueType(UA_Server *server, UA_Variant *value,
+ const UA_NodeId *targetDataTypeId) {
+ /* If the value is empty, there is nothing we can do here */
+ if(!value->type)
+ return;
+
const UA_DataType *targetDataType = UA_findDataType(targetDataTypeId);
if(!targetDataType)
return;
@@ -35703,7 +38622,7 @@ adjustValue(UA_Server *server, UA_Variant *value,
}
/* An enum was sent as an int32, or an opaque type as a bytestring. This
- * is detected with the typeIndex indicating the "true" datatype. */
+ * is detected with the typeKind indicating the "true" datatype. */
UA_DataTypeKind te1 = typeEquivalence(targetDataType);
UA_DataTypeKind te2 = typeEquivalence(value->type);
if(te1 == te2 && te1 <= UA_DATATYPEKIND_ENUM) {
@@ -35723,15 +38642,16 @@ writeArrayDimensionsAttribute(UA_Server *server, UA_Session *session,
/* If this is a variabletype, there must be no instances or subtypes of it
* when we do the change */
- if(node->nodeClass == UA_NODECLASS_VARIABLETYPE &&
- UA_Node_hasSubTypeOrInstances((UA_Node*)node)) {
+ if(node->head.nodeClass == UA_NODECLASS_VARIABLETYPE &&
+ UA_Node_hasSubTypeOrInstances(&node->head)) {
UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_SERVER,
"Cannot change a variable type with existing instances");
return UA_STATUSCODE_BADINTERNALERROR;
}
/* Check that the array dimensions match with the valuerank */
- if(!compatibleValueRankArrayDimensions(server, session, node->valueRank, arrayDimensionsSize)) {
+ if(!compatibleValueRankArrayDimensions(server, session, node->valueRank,
+ arrayDimensionsSize)) {
UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER,
"Cannot write the ArrayDimensions. The ValueRank does not match.");
return UA_STATUSCODE_BADTYPEMISMATCH;
@@ -35754,7 +38674,8 @@ writeArrayDimensionsAttribute(UA_Server *server, UA_Session *session,
if(retval != UA_STATUSCODE_GOOD)
return retval;
if(value.hasValue) {
- if(!compatibleValueArrayDimensions(&value.value, arrayDimensionsSize, arrayDimensions))
+ if(!compatibleValueArrayDimensions(&value.value, arrayDimensionsSize,
+ arrayDimensions))
retval = UA_STATUSCODE_BADTYPEMISMATCH;
UA_DataValue_clear(&value);
if(retval != UA_STATUSCODE_GOOD) {
@@ -35789,8 +38710,8 @@ writeValueRankAttribute(UA_Server *server, UA_Session *session,
/* If this is a variabletype, there must be no instances or subtypes of it
* when we do the change */
- if(node->nodeClass == UA_NODECLASS_VARIABLETYPE &&
- UA_Node_hasSubTypeOrInstances((const UA_Node*)node))
+ if(node->head.nodeClass == UA_NODECLASS_VARIABLETYPE &&
+ UA_Node_hasSubTypeOrInstances(&node->head))
return UA_STATUSCODE_BADINTERNALERROR;
/* Check if the valuerank of the variabletype allows the change. */
@@ -35834,12 +38755,12 @@ writeDataTypeAttribute(UA_Server *server, UA_Session *session,
/* If this is a variabletype, there must be no instances or subtypes of it
when we do the change */
- if(node->nodeClass == UA_NODECLASS_VARIABLETYPE &&
- UA_Node_hasSubTypeOrInstances((const UA_Node*)node))
+ if(node->head.nodeClass == UA_NODECLASS_VARIABLETYPE &&
+ UA_Node_hasSubTypeOrInstances(&node->head))
return UA_STATUSCODE_BADINTERNALERROR;
/* Does the new type match the constraints of the variabletype? */
- if(!compatibleDataType(server, dataType, &type->dataType, false))
+ if(!compatibleDataTypes(server, dataType, &type->dataType))
return UA_STATUSCODE_BADTYPEMISMATCH;
/* Check if the current value would match the new type */
@@ -35849,9 +38770,10 @@ writeDataTypeAttribute(UA_Server *server, UA_Session *session,
if(retval != UA_STATUSCODE_GOOD)
return retval;
if(value.hasValue) {
+ const char *reason; /* temp value */
if(!compatibleValue(server, session, dataType, node->valueRank,
node->arrayDimensionsSize, node->arrayDimensions,
- &value.value, NULL))
+ &value.value, NULL, &reason))
retval = UA_STATUSCODE_BADTYPEMISMATCH;
UA_DataValue_clear(&value);
if(retval != UA_STATUSCODE_GOOD) {
@@ -35925,13 +38847,15 @@ writeValueAttributeWithRange(UA_VariableNode *node, const UA_DataValue *value,
/* Stack layout: ... | node */
static UA_StatusCode
-writeValueAttribute(UA_Server *server, UA_Session *session,
- UA_VariableNode *node, const UA_DataValue *value,
- const UA_String *indexRange) {
+writeNodeValueAttribute(UA_Server *server, UA_Session *session,
+ UA_VariableNode *node, const UA_DataValue *value,
+ const UA_String *indexRange) {
UA_assert(node != NULL);
+ UA_assert(session != NULL);
/* Parse the range */
UA_NumericRange range;
+ range.dimensions = NULL;
UA_NumericRange *rangeptr = NULL;
UA_StatusCode retval = UA_STATUSCODE_GOOD;
if(indexRange && indexRange->length > 0) {
@@ -35947,7 +38871,7 @@ writeValueAttribute(UA_Server *server, UA_Session *session,
/* Type checking. May change the type of editableValue */
if(value->hasValue && value->value.type) {
- adjustValue(server, &adjustedValue.value, &node->dataType);
+ adjustValueType(server, &adjustedValue.value, &node->dataType);
/* The value may be an extension object, especially the nodeset compiler
* uses extension objects to write variable values. If value is an
@@ -35959,88 +38883,125 @@ writeValueAttribute(UA_Server *server, UA_Session *session,
value->value.type->typeId.identifier.numeric == UA_NS0ID_STRUCTURE)
nodeDataTypePtr = &nodeDataType;
+ const char *reason;
if(!compatibleValue(server, session, nodeDataTypePtr, node->valueRank,
node->arrayDimensionsSize, node->arrayDimensions,
- &adjustedValue.value, rangeptr)) {
- if(rangeptr)
- UA_free(range.dimensions);
+ &adjustedValue.value, rangeptr, &reason)) {
+ UA_LOG_NODEID_WARNING(&node->head.nodeId,
+ if(session == &server->adminSession) {
+ /* If the value is written via the local API, log a warning */
+ UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Writing the value of Node %.*s failed with the "
+ "following reason: %s",
+ (int)nodeIdStr.length, nodeIdStr.data, reason);
+ } else {
+ /* Don't spam the logs if writing from remote failed */
+ UA_LOG_DEBUG_SESSION(&server->config.logger, session,
+ "Writing the value of Node %.*s failed with the "
+ "following reason: %s",
+ (int)nodeIdStr.length, nodeIdStr.data, reason);
+ });
+ if(rangeptr && rangeptr->dimensions != NULL)
+ UA_free(rangeptr->dimensions);
return UA_STATUSCODE_BADTYPEMISMATCH;
}
}
- /* Ok, do it */
- if(node->valueSource == UA_VALUESOURCE_DATA) {
- /* Set the source timestamp if there is none */
- UA_DateTime now = UA_DateTime_now();
- if(!adjustedValue.hasSourceTimestamp) {
- adjustedValue.sourceTimestamp = now;
- adjustedValue.hasSourceTimestamp = true;
- }
+ /* Set the source timestamp if there is none */
+ UA_DateTime now = UA_DateTime_now();
+ if(!adjustedValue.hasSourceTimestamp) {
+ adjustedValue.sourceTimestamp = now;
+ adjustedValue.hasSourceTimestamp = true;
+ }
- if(!adjustedValue.hasServerTimestamp) {
- adjustedValue.serverTimestamp = now;
- adjustedValue.hasServerTimestamp = true;
- }
+ /* Update the timestamp when the value was last updated in the server */
+ adjustedValue.serverTimestamp = now;
+ adjustedValue.hasServerTimestamp = true;
- if(!rangeptr)
- retval = writeValueAttributeWithoutRange(node, &adjustedValue);
- else
- retval = writeValueAttributeWithRange(node, &adjustedValue, rangeptr);
+ switch(node->valueBackend.backendType) {
+ case UA_VALUEBACKENDTYPE_NONE:
+ /* Ok, do it */
+ if(node->valueSource == UA_VALUESOURCE_DATA) {
+ if(!rangeptr)
+ retval = writeValueAttributeWithoutRange(node, &adjustedValue);
+ else
+ retval = writeValueAttributeWithRange(node, &adjustedValue, rangeptr);
#ifdef UA_ENABLE_HISTORIZING
- /* node is a UA_VariableNode*, but it may also point to a UA_VariableTypeNode */
- /* UA_VariableTypeNode doesn't have the historizing attribute */
- if(retval == UA_STATUSCODE_GOOD && node->nodeClass == UA_NODECLASS_VARIABLE &&
- server->config.historyDatabase.setValue) {
- UA_UNLOCK(server->serviceMutex);
- server->config.historyDatabase.
- setValue(server, server->config.historyDatabase.context,
- &session->sessionId, session->sessionHandle,
- &node->nodeId, node->historizing, &adjustedValue);
- UA_LOCK(server->serviceMutex);
- }
+ /* node is a UA_VariableNode*, but it may also point to a
+ UA_VariableTypeNode */
+ /* UA_VariableTypeNode doesn't have the historizing attribute */
+ if(retval == UA_STATUSCODE_GOOD &&
+ node->head.nodeClass == UA_NODECLASS_VARIABLE &&
+ server->config.historyDatabase.setValue) {
+ UA_UNLOCK(&server->serviceMutex);
+ server->config.historyDatabase.
+ setValue(server, server->config.historyDatabase.context,
+ &session->sessionId, session->sessionHandle,
+ &node->head.nodeId, node->historizing, &adjustedValue);
+ UA_LOCK(&server->serviceMutex);
+ }
#endif
- /* Callback after writing */
- if(retval == UA_STATUSCODE_GOOD && node->value.data.callback.onWrite) {
- UA_UNLOCK(server->serviceMutex)
- node->value.data.callback.
- onWrite(server, &session->sessionId, session->sessionHandle,
- &node->nodeId, node->context, rangeptr, &adjustedValue);
- UA_LOCK(server->serviceMutex);
+ /* Callback after writing */
+ if(retval == UA_STATUSCODE_GOOD && node->value.data.callback.onWrite) {
+ UA_UNLOCK(&server->serviceMutex);
+ node->value.data.callback.
+ onWrite(server, &session->sessionId, session->sessionHandle,
+ &node->head.nodeId, node->head.context,
+ rangeptr, &adjustedValue);
+ UA_LOCK(&server->serviceMutex);
- }
- } else {
- if(node->value.dataSource.write) {
- UA_UNLOCK(server->serviceMutex);
- retval = node->value.dataSource.
- write(server, &session->sessionId, session->sessionHandle,
- &node->nodeId, node->context, rangeptr, &adjustedValue);
- UA_LOCK(server->serviceMutex);
- } else {
- retval = UA_STATUSCODE_BADWRITENOTSUPPORTED;
- }
+ }
+ } else {
+ if(node->value.dataSource.write) {
+ UA_UNLOCK(&server->serviceMutex);
+ retval = node->value.dataSource.
+ write(server, &session->sessionId, session->sessionHandle,
+ &node->head.nodeId, node->head.context,
+ rangeptr, &adjustedValue);
+ UA_LOCK(&server->serviceMutex);
+ } else {
+ retval = UA_STATUSCODE_BADWRITENOTSUPPORTED;
+ }
+ }
+ break;
+ case UA_VALUEBACKENDTYPE_INTERNAL:
+ break;
+ case UA_VALUEBACKENDTYPE_DATA_SOURCE_CALLBACK:
+ break;
+ case UA_VALUEBACKENDTYPE_EXTERNAL:
+ if(node->valueBackend.backend.external.callback.userWrite == NULL){
+ if(rangeptr && rangeptr->dimensions != NULL)
+ UA_free(rangeptr->dimensions);
+ return UA_STATUSCODE_BADWRITENOTSUPPORTED;
+ }
+ retval = node->valueBackend.backend.external.callback.
+ userWrite(server, &session->sessionId, session->sessionHandle,
+ &node->head.nodeId, node->head.context,
+ rangeptr, &adjustedValue);
+ break;
}
/* Clean up */
- if(rangeptr)
- UA_free(range.dimensions);
+ if(rangeptr && rangeptr->dimensions != NULL)
+ UA_free(rangeptr->dimensions);
return retval;
}
static UA_StatusCode
writeIsAbstractAttribute(UA_Node *node, UA_Boolean value) {
- switch(node->nodeClass) {
+ switch(node->head.nodeClass) {
case UA_NODECLASS_OBJECTTYPE:
- ((UA_ObjectTypeNode*)node)->isAbstract = value;
+ node->objectTypeNode.isAbstract = value;
break;
case UA_NODECLASS_REFERENCETYPE:
- ((UA_ReferenceTypeNode*)node)->isAbstract = value;
+ node->referenceTypeNode.isAbstract = value;
break;
case UA_NODECLASS_VARIABLETYPE:
- ((UA_VariableTypeNode*)node)->isAbstract = value;
+ node->variableTypeNode.isAbstract = value;
break;
case UA_NODECLASS_DATATYPE:
- ((UA_DataTypeNode*)node)->isAbstract = value;
+ node->dataTypeNode.isAbstract = value;
break;
default:
return UA_STATUSCODE_BADNODECLASSINVALID;
@@ -36069,7 +39030,7 @@ writeIsAbstractAttribute(UA_Node *node, UA_Boolean value) {
}
#define CHECK_NODECLASS_WRITE(CLASS) \
- if((node->nodeClass & (CLASS)) == 0) { \
+ if((node->head.nodeClass & (CLASS)) == 0) { \
retval = UA_STATUSCODE_BADNODECLASSINVALID; \
break; \
}
@@ -36082,7 +39043,7 @@ writeIsAbstractAttribute(UA_Node *node, UA_Boolean value) {
#define GET_NODETYPE \
type = (const UA_VariableTypeNode*) \
- getNodeType(server, node); \
+ getNodeType(server, &node->head); \
if(!type) { \
retval = UA_STATUSCODE_BADTYPEMISMATCH; \
break; \
@@ -36101,15 +39062,49 @@ updateLocalizedText(const UA_LocalizedText *source, UA_LocalizedText *target) {
return UA_STATUSCODE_GOOD;
}
+/* Trigger sampling if a MonitoredItem surveils the attribute with no sampling
+ * interval */
+#ifdef UA_ENABLE_SUBSCRIPTIONS
+static void
+triggerImmediateDataChange(UA_Server *server, UA_Session *session,
+ UA_Node *node, const UA_WriteValue *wvalue) {
+ for(UA_MonitoredItem *mon = node->head.monitoredItems; mon != NULL; mon = mon->next) {
+ if(mon->itemToMonitor.attributeId != wvalue->attributeId)
+ continue;
+ UA_DataValue value;
+ UA_DataValue_init(&value);
+ ReadWithNode(node, server, session, mon->timestampsToReturn,
+ &mon->itemToMonitor, &value);
+ UA_Subscription *sub = mon->subscription;
+ UA_StatusCode res = sampleCallbackWithValue(server, sub, mon, &value);
+ if(res != UA_STATUSCODE_GOOD) {
+ UA_DataValue_clear(&value);
+ UA_LOG_WARNING_SUBSCRIPTION(&server->config.logger, sub,
+ "MonitoredItem %" PRIi32 " | "
+ "Sampling returned the statuscode %s",
+ mon->monitoredItemId,
+ UA_StatusCode_name(res));
+ }
+ }
+}
+#endif
+
/* This function implements the main part of the write service and operates on a
copy of the node (not in single-threaded mode). */
static UA_StatusCode
copyAttributeIntoNode(UA_Server *server, UA_Session *session,
UA_Node *node, const UA_WriteValue *wvalue) {
+ UA_assert(session != NULL);
const void *value = wvalue->value.value.data;
- UA_UInt32 userWriteMask = getUserWriteMask(server, session, node);
+ UA_UInt32 userWriteMask = getUserWriteMask(server, session, &node->head);
UA_StatusCode retval = UA_STATUSCODE_GOOD;
+ UA_LOG_NODEID_DEBUG(&node->head.nodeId,
+ UA_LOG_DEBUG_SESSION(&server->config.logger, session,
+ "Write attribute %"PRIi32 " of Node %.*s",
+ wvalue->attributeId, (int)nodeIdStr.length,
+ nodeIdStr.data));
+
const UA_VariableTypeNode *type;
switch(wvalue->attributeId) {
@@ -36125,17 +39120,19 @@ copyAttributeIntoNode(UA_Server *server, UA_Session *session,
case UA_ATTRIBUTEID_DISPLAYNAME:
CHECK_USERWRITEMASK(UA_WRITEMASK_DISPLAYNAME);
CHECK_DATATYPE_SCALAR(LOCALIZEDTEXT);
- retval = updateLocalizedText((const UA_LocalizedText *)value, &node->displayName);
+ retval = updateLocalizedText((const UA_LocalizedText *)value,
+ &node->head.displayName);
break;
case UA_ATTRIBUTEID_DESCRIPTION:
CHECK_USERWRITEMASK(UA_WRITEMASK_DESCRIPTION);
CHECK_DATATYPE_SCALAR(LOCALIZEDTEXT);
- retval = updateLocalizedText((const UA_LocalizedText *)value, &node->description);
+ retval = updateLocalizedText((const UA_LocalizedText *)value,
+ &node->head.description);
break;
case UA_ATTRIBUTEID_WRITEMASK:
CHECK_USERWRITEMASK(UA_WRITEMASK_WRITEMASK);
CHECK_DATATYPE_SCALAR(UINT32);
- node->writeMask = *(const UA_UInt32*)value;
+ node->head.writeMask = *(const UA_UInt32*)value;
break;
case UA_ATTRIBUTEID_ISABSTRACT:
CHECK_USERWRITEMASK(UA_WRITEMASK_ISABSTRACT);
@@ -36146,42 +39143,42 @@ copyAttributeIntoNode(UA_Server *server, UA_Session *session,
CHECK_NODECLASS_WRITE(UA_NODECLASS_REFERENCETYPE);
CHECK_USERWRITEMASK(UA_WRITEMASK_SYMMETRIC);
CHECK_DATATYPE_SCALAR(BOOLEAN);
- ((UA_ReferenceTypeNode*)node)->symmetric = *(const UA_Boolean*)value;
+ node->referenceTypeNode.symmetric = *(const UA_Boolean*)value;
break;
case UA_ATTRIBUTEID_INVERSENAME:
CHECK_NODECLASS_WRITE(UA_NODECLASS_REFERENCETYPE);
CHECK_USERWRITEMASK(UA_WRITEMASK_INVERSENAME);
CHECK_DATATYPE_SCALAR(LOCALIZEDTEXT);
retval = updateLocalizedText((const UA_LocalizedText *)value,
- &((UA_ReferenceTypeNode*)node)->inverseName);
+ &node->referenceTypeNode.inverseName);
break;
case UA_ATTRIBUTEID_CONTAINSNOLOOPS:
CHECK_NODECLASS_WRITE(UA_NODECLASS_VIEW);
CHECK_USERWRITEMASK(UA_WRITEMASK_CONTAINSNOLOOPS);
CHECK_DATATYPE_SCALAR(BOOLEAN);
- ((UA_ViewNode*)node)->containsNoLoops = *(const UA_Boolean*)value;
+ node->viewNode.containsNoLoops = *(const UA_Boolean*)value;
break;
case UA_ATTRIBUTEID_EVENTNOTIFIER:
CHECK_NODECLASS_WRITE(UA_NODECLASS_VIEW | UA_NODECLASS_OBJECT);
CHECK_USERWRITEMASK(UA_WRITEMASK_EVENTNOTIFIER);
CHECK_DATATYPE_SCALAR(BYTE);
- if(node->nodeClass == UA_NODECLASS_VIEW) {
- ((UA_ViewNode*)node)->eventNotifier = *(const UA_Byte*)value;
+ if(node->head.nodeClass == UA_NODECLASS_VIEW) {
+ node->viewNode.eventNotifier = *(const UA_Byte*)value;
} else {
- ((UA_ObjectNode*)node)->eventNotifier = *(const UA_Byte*)value;
+ node->objectNode.eventNotifier = *(const UA_Byte*)value;
}
break;
case UA_ATTRIBUTEID_VALUE:
CHECK_NODECLASS_WRITE(UA_NODECLASS_VARIABLE | UA_NODECLASS_VARIABLETYPE);
- if(node->nodeClass == UA_NODECLASS_VARIABLE) {
+ if(node->head.nodeClass == UA_NODECLASS_VARIABLE) {
/* The access to a value variable is granted via the AccessLevel
* and UserAccessLevel attributes */
- UA_Byte accessLevel = getAccessLevel(server, session, (const UA_VariableNode*)node);
+ UA_Byte accessLevel = getAccessLevel(server, session, &node->variableNode);
if(!(accessLevel & (UA_ACCESSLEVELMASK_WRITE))) {
retval = UA_STATUSCODE_BADNOTWRITABLE;
break;
}
- accessLevel = getUserAccessLevel(server, session, (const UA_VariableNode*)node);
+ accessLevel = getUserAccessLevel(server, session, &node->variableNode);
if(!(accessLevel & (UA_ACCESSLEVELMASK_WRITE))) {
retval = UA_STATUSCODE_BADUSERACCESSDENIED;
break;
@@ -36189,15 +39186,15 @@ copyAttributeIntoNode(UA_Server *server, UA_Session *session,
} else { /* UA_NODECLASS_VARIABLETYPE */
CHECK_USERWRITEMASK(UA_WRITEMASK_VALUEFORVARIABLETYPE);
}
- retval = writeValueAttribute(server, session, (UA_VariableNode*)node,
- &wvalue->value, &wvalue->indexRange);
+ retval = writeNodeValueAttribute(server, session, &node->variableNode,
+ &wvalue->value, &wvalue->indexRange);
break;
case UA_ATTRIBUTEID_DATATYPE:
CHECK_NODECLASS_WRITE(UA_NODECLASS_VARIABLE | UA_NODECLASS_VARIABLETYPE);
CHECK_USERWRITEMASK(UA_WRITEMASK_DATATYPE);
CHECK_DATATYPE_SCALAR(NODEID);
- GET_NODETYPE
- retval = writeDataTypeAttribute(server, session, (UA_VariableNode*)node,
+ GET_NODETYPE;
+ retval = writeDataTypeAttribute(server, session, &node->variableNode,
type, (const UA_NodeId*)value);
UA_NODESTORE_RELEASE(server, (const UA_Node*)type);
break;
@@ -36205,8 +39202,8 @@ copyAttributeIntoNode(UA_Server *server, UA_Session *session,
CHECK_NODECLASS_WRITE(UA_NODECLASS_VARIABLE | UA_NODECLASS_VARIABLETYPE);
CHECK_USERWRITEMASK(UA_WRITEMASK_VALUERANK);
CHECK_DATATYPE_SCALAR(INT32);
- GET_NODETYPE
- retval = writeValueRankAttribute(server, session, (UA_VariableNode*)node,
+ GET_NODETYPE;
+ retval = writeValueRankAttribute(server, session, &node->variableNode,
type, *(const UA_Int32*)value);
UA_NODESTORE_RELEASE(server, (const UA_Node*)type);
break;
@@ -36214,8 +39211,8 @@ copyAttributeIntoNode(UA_Server *server, UA_Session *session,
CHECK_NODECLASS_WRITE(UA_NODECLASS_VARIABLE | UA_NODECLASS_VARIABLETYPE);
CHECK_USERWRITEMASK(UA_WRITEMASK_ARRRAYDIMENSIONS);
CHECK_DATATYPE_ARRAY(UINT32);
- GET_NODETYPE
- retval = writeArrayDimensionsAttribute(server, session, (UA_VariableNode*)node,
+ GET_NODETYPE;
+ retval = writeArrayDimensionsAttribute(server, session, &node->variableNode,
type, wvalue->value.value.arrayLength,
(UA_UInt32 *)wvalue->value.value.data);
UA_NODESTORE_RELEASE(server, (const UA_Node*)type);
@@ -36224,51 +39221,64 @@ copyAttributeIntoNode(UA_Server *server, UA_Session *session,
CHECK_NODECLASS_WRITE(UA_NODECLASS_VARIABLE);
CHECK_USERWRITEMASK(UA_WRITEMASK_ACCESSLEVEL);
CHECK_DATATYPE_SCALAR(BYTE);
- ((UA_VariableNode*)node)->accessLevel = *(const UA_Byte*)value;
+ node->variableNode.accessLevel = *(const UA_Byte*)value;
break;
case UA_ATTRIBUTEID_MINIMUMSAMPLINGINTERVAL:
CHECK_NODECLASS_WRITE(UA_NODECLASS_VARIABLE);
CHECK_USERWRITEMASK(UA_WRITEMASK_MINIMUMSAMPLINGINTERVAL);
CHECK_DATATYPE_SCALAR(DOUBLE);
- ((UA_VariableNode*)node)->minimumSamplingInterval = *(const UA_Double*)value;
+ node->variableNode.minimumSamplingInterval = *(const UA_Double*)value;
break;
case UA_ATTRIBUTEID_HISTORIZING:
CHECK_NODECLASS_WRITE(UA_NODECLASS_VARIABLE);
CHECK_USERWRITEMASK(UA_WRITEMASK_HISTORIZING);
CHECK_DATATYPE_SCALAR(BOOLEAN);
- ((UA_VariableNode*)node)->historizing = *(const UA_Boolean*)value;
+ node->variableNode.historizing = *(const UA_Boolean*)value;
break;
case UA_ATTRIBUTEID_EXECUTABLE:
CHECK_NODECLASS_WRITE(UA_NODECLASS_METHOD);
CHECK_USERWRITEMASK(UA_WRITEMASK_EXECUTABLE);
CHECK_DATATYPE_SCALAR(BOOLEAN);
- ((UA_MethodNode*)node)->executable = *(const UA_Boolean*)value;
+ node->methodNode.executable = *(const UA_Boolean*)value;
break;
default:
retval = UA_STATUSCODE_BADATTRIBUTEIDINVALID;
break;
}
- if(retval != UA_STATUSCODE_GOOD)
+
+ /* Check if writing succeeded */
+ if(retval != UA_STATUSCODE_GOOD) {
UA_LOG_INFO_SESSION(&server->config.logger, session,
"WriteRequest returned status code %s",
UA_StatusCode_name(retval));
- return retval;
+ return retval;
+ }
+
+ /* Trigger MonitoredItems with no SamplingInterval */
+#ifdef UA_ENABLE_SUBSCRIPTIONS
+ triggerImmediateDataChange(server, session, node, wvalue);
+#endif
+
+ return UA_STATUSCODE_GOOD;
}
static void
Operation_Write(UA_Server *server, UA_Session *session, void *context,
- UA_WriteValue *wv, UA_StatusCode *result) {
+ const UA_WriteValue *wv, UA_StatusCode *result) {
+ UA_assert(session != NULL);
*result = UA_Server_editNode(server, session, &wv->nodeId,
- (UA_EditNodeCallback)copyAttributeIntoNode, wv);
+ (UA_EditNodeCallback)copyAttributeIntoNode,
+ (void*)(uintptr_t)wv);
}
void
Service_Write(UA_Server *server, UA_Session *session,
const UA_WriteRequest *request,
UA_WriteResponse *response) {
+ UA_assert(session != NULL);
UA_LOG_DEBUG_SESSION(&server->config.logger, session,
"Processing WriteRequest");
- UA_LOCK_ASSERT(server->serviceMutex, 1);
+ UA_LOCK_ASSERT(&server->serviceMutex, 1);
if(server->config.maxNodesPerWrite != 0 &&
request->nodesToWriteSize > server->config.maxNodesPerWrite) {
@@ -36276,46 +39286,45 @@ Service_Write(UA_Server *server, UA_Session *session,
return;
}
- UA_LOCK_ASSERT(server->serviceMutex, 1);
+ UA_LOCK_ASSERT(&server->serviceMutex, 1);
response->responseHeader.serviceResult =
- UA_Server_processServiceOperations(server, session, (UA_ServiceOperation)Operation_Write, NULL,
- &request->nodesToWriteSize, &UA_TYPES[UA_TYPES_WRITEVALUE],
- &response->resultsSize, &UA_TYPES[UA_TYPES_STATUSCODE]);
+ UA_Server_processServiceOperations(server, session,
+ (UA_ServiceOperation)Operation_Write, NULL,
+ &request->nodesToWriteSize,
+ &UA_TYPES[UA_TYPES_WRITEVALUE],
+ &response->resultsSize,
+ &UA_TYPES[UA_TYPES_STATUSCODE]);
}
UA_StatusCode
-writeWithSession(UA_Server *server, UA_Session *session,
- const UA_WriteValue *value) {
- return UA_Server_editNode(server, session, &value->nodeId,
- (UA_EditNodeCallback)copyAttributeIntoNode,
- /* casting away const qualifier because callback uses const anyway */
- (UA_WriteValue *)(uintptr_t)value);
+UA_Server_write(UA_Server *server, const UA_WriteValue *value) {
+ UA_StatusCode res = UA_STATUSCODE_GOOD;
+ UA_LOCK(&server->serviceMutex);
+ Operation_Write(server, &server->adminSession, NULL, value, &res);
+ UA_UNLOCK(&server->serviceMutex);
+ return res;
}
+/* Convenience function to be wrapped into inline functions */
UA_StatusCode
-writeAttribute(UA_Server *server, const UA_WriteValue *value) {
- UA_LOCK_ASSERT(server->serviceMutex, 1);
- return UA_Server_editNode(server, &server->adminSession, &value->nodeId,
- (UA_EditNodeCallback)copyAttributeIntoNode,
- /* casting away const qualifier because callback uses const anyway */
- (UA_WriteValue *)(uintptr_t)value);
+__UA_Server_write(UA_Server *server, const UA_NodeId *nodeId,
+ const UA_AttributeId attributeId,
+ const UA_DataType *attr_type, const void *attr) {
+ UA_LOCK(&server->serviceMutex);
+ UA_StatusCode res = writeAttribute(server, &server->adminSession,
+ nodeId, attributeId, attr, attr_type);
+ UA_UNLOCK(&server->serviceMutex);
+ return res;
}
+/* Internal convenience function */
UA_StatusCode
-UA_Server_write(UA_Server *server, const UA_WriteValue *value) {
- UA_LOCK(server->serviceMutex);
- UA_StatusCode retval = writeAttribute(server, value);
- UA_UNLOCK(server->serviceMutex);
- return retval;
-}
+writeAttribute(UA_Server *server, UA_Session *session,
+ const UA_NodeId *nodeId, const UA_AttributeId attributeId,
+ const void *attr, const UA_DataType *attr_type) {
+ UA_LOCK_ASSERT(&server->serviceMutex, 1);
-UA_StatusCode
-writeWithWriteValue(UA_Server *server, const UA_NodeId *nodeId,
- const UA_AttributeId attributeId,
- const UA_DataType *attr_type,
- const void *attr) {
- UA_LOCK_ASSERT(server->serviceMutex, 1);
UA_WriteValue wvalue;
UA_WriteValue_init(&wvalue);
wvalue.nodeId = *nodeId;
@@ -36330,19 +39339,10 @@ writeWithWriteValue(UA_Server *server, const UA_NodeId *nodeId,
UA_Variant_setScalar(&wvalue.value.value,
(void*)(uintptr_t)attr, attr_type);
}
- return writeAttribute(server, &wvalue);
-}
-/* Convenience function to be wrapped into inline functions */
-UA_StatusCode
-__UA_Server_write(UA_Server *server, const UA_NodeId *nodeId,
- const UA_AttributeId attributeId,
- const UA_DataType *attr_type,
- const void *attr) {
- UA_LOCK(server->serviceMutex);
- UA_StatusCode retval = writeWithWriteValue(server, nodeId, attributeId, attr_type, attr);
- UA_UNLOCK(server->serviceMutex);
- return retval;
+ UA_StatusCode res = UA_STATUSCODE_GOOD;
+ Operation_Write(server, session, NULL, &wvalue, &res);
+ return res;
}
#ifdef UA_ENABLE_HISTORIZING
@@ -36362,7 +39362,12 @@ void
Service_HistoryRead(UA_Server *server, UA_Session *session,
const UA_HistoryReadRequest *request,
UA_HistoryReadResponse *response) {
- UA_LOCK_ASSERT(server->serviceMutex, 1);
+ UA_assert(session != NULL);
+ UA_LOCK_ASSERT(&server->serviceMutex, 1);
+ if(server->config.historyDatabase.context == NULL) {
+ response->responseHeader.serviceResult = UA_STATUSCODE_BADNOTSUPPORTED;
+ return;
+ }
if(request->historyReadDetails.encoding != UA_EXTENSIONOBJECT_DECODED) {
response->responseHeader.serviceResult = UA_STATUSCODE_BADNOTSUPPORTED;
@@ -36371,31 +39376,32 @@ Service_HistoryRead(UA_Server *server, UA_Session *session,
const UA_DataType *historyDataType = &UA_TYPES[UA_TYPES_HISTORYDATA];
UA_HistoryDatabase_readFunc readHistory = NULL;
- switch(request->historyReadDetails.content.decoded.type->typeIndex) {
- case UA_TYPES_READRAWMODIFIEDDETAILS: {
- UA_ReadRawModifiedDetails *details = (UA_ReadRawModifiedDetails*)
- request->historyReadDetails.content.decoded.data;
- if(!details->isReadModified) {
- readHistory = (UA_HistoryDatabase_readFunc)server->config.historyDatabase.readRaw;
- } else {
- historyDataType = &UA_TYPES[UA_TYPES_HISTORYMODIFIEDDATA];
- readHistory = (UA_HistoryDatabase_readFunc)server->config.historyDatabase.readModified;
- }
- break;
- }
- case UA_TYPES_READEVENTDETAILS:
- historyDataType = &UA_TYPES[UA_TYPES_HISTORYEVENT];
- readHistory = (UA_HistoryDatabase_readFunc)server->config.historyDatabase.readEvent;
- break;
- case UA_TYPES_READPROCESSEDDETAILS:
- readHistory = (UA_HistoryDatabase_readFunc)server->config.historyDatabase.readProcessed;
- break;
- case UA_TYPES_READATTIMEDETAILS:
- readHistory = (UA_HistoryDatabase_readFunc)server->config.historyDatabase.readAtTime;
- break;
- }
-
- if(!readHistory) {
+ if(request->historyReadDetails.content.decoded.type ==
+ &UA_TYPES[UA_TYPES_READRAWMODIFIEDDETAILS]) {
+ UA_ReadRawModifiedDetails *details = (UA_ReadRawModifiedDetails*)
+ request->historyReadDetails.content.decoded.data;
+ if(!details->isReadModified) {
+ readHistory = (UA_HistoryDatabase_readFunc)
+ server->config.historyDatabase.readRaw;
+ } else {
+ historyDataType = &UA_TYPES[UA_TYPES_HISTORYMODIFIEDDATA];
+ readHistory = (UA_HistoryDatabase_readFunc)
+ server->config.historyDatabase.readModified;
+ }
+ } else if(request->historyReadDetails.content.decoded.type ==
+ &UA_TYPES[UA_TYPES_READEVENTDETAILS]) {
+ historyDataType = &UA_TYPES[UA_TYPES_HISTORYEVENT];
+ readHistory = (UA_HistoryDatabase_readFunc)
+ server->config.historyDatabase.readEvent;
+ } else if(request->historyReadDetails.content.decoded.type ==
+ &UA_TYPES[UA_TYPES_READPROCESSEDDETAILS]) {
+ readHistory = (UA_HistoryDatabase_readFunc)
+ server->config.historyDatabase.readProcessed;
+ } else if(request->historyReadDetails.content.decoded.type ==
+ &UA_TYPES[UA_TYPES_READATTIMEDETAILS]) {
+ readHistory = (UA_HistoryDatabase_readFunc)
+ server->config.historyDatabase.readAtTime;
+ } else {
/* TODO handle more request->historyReadDetails.content.decoded.type types */
response->responseHeader.serviceResult = UA_STATUSCODE_BADHISTORYOPERATIONUNSUPPORTED;
return;
@@ -36435,12 +39441,11 @@ Service_HistoryRead(UA_Server *server, UA_Session *session,
for(size_t i = 0; i < response->resultsSize; ++i) {
void * data = UA_new(historyDataType);
- response->results[i].historyData.encoding = UA_EXTENSIONOBJECT_DECODED;
- response->results[i].historyData.content.decoded.type = historyDataType;
- response->results[i].historyData.content.decoded.data = data;
+ UA_ExtensionObject_setValue(&response->results[i].historyData,
+ data, historyDataType);
historyData[i] = data;
}
- UA_UNLOCK(server->serviceMutex);
+ UA_UNLOCK(&server->serviceMutex);
readHistory(server, server->config.historyDatabase.context,
&session->sessionId, session->sessionHandle,
&request->requestHeader,
@@ -36449,7 +39454,7 @@ Service_HistoryRead(UA_Server *server, UA_Session *session,
request->releaseContinuationPoints,
request->nodesToReadSize, request->nodesToRead,
response, historyData);
- UA_LOCK(server->serviceMutex);
+ UA_LOCK(&server->serviceMutex);
UA_free(historyData);
}
@@ -36457,7 +39462,8 @@ void
Service_HistoryUpdate(UA_Server *server, UA_Session *session,
const UA_HistoryUpdateRequest *request,
UA_HistoryUpdateResponse *response) {
- UA_LOCK_ASSERT(server->serviceMutex, 1);
+ UA_assert(session != NULL);
+ UA_LOCK_ASSERT(&server->serviceMutex, 1);
response->resultsSize = request->historyUpdateDetailsSize;
response->results = (UA_HistoryUpdateResult*)
@@ -36478,35 +39484,36 @@ Service_HistoryUpdate(UA_Server *server, UA_Session *session,
const UA_DataType *updateDetailsType =
request->historyUpdateDetails[i].content.decoded.type;
void *updateDetailsData = request->historyUpdateDetails[i].content.decoded.data;
+
if(updateDetailsType == &UA_TYPES[UA_TYPES_UPDATEDATADETAILS]) {
- if(server->config.historyDatabase.updateData) {
- UA_UNLOCK(server->serviceMutex);
- server->config.historyDatabase.
- updateData(server, server->config.historyDatabase.context,
- &session->sessionId, session->sessionHandle,
- &request->requestHeader,
- (UA_UpdateDataDetails*)updateDetailsData,
- &response->results[i]);
- UA_LOCK(server->serviceMutex);
- } else {
+ if(!server->config.historyDatabase.updateData) {
response->results[i].statusCode = UA_STATUSCODE_BADNOTSUPPORTED;
+ continue;
}
+ UA_UNLOCK(&server->serviceMutex);
+ server->config.historyDatabase.
+ updateData(server, server->config.historyDatabase.context,
+ &session->sessionId, session->sessionHandle,
+ &request->requestHeader,
+ (UA_UpdateDataDetails*)updateDetailsData,
+ &response->results[i]);
+ UA_LOCK(&server->serviceMutex);
continue;
}
if(updateDetailsType == &UA_TYPES[UA_TYPES_DELETERAWMODIFIEDDETAILS]) {
- if(server->config.historyDatabase.deleteRawModified) {
- UA_UNLOCK(server->serviceMutex);
- server->config.historyDatabase.
- deleteRawModified(server, server->config.historyDatabase.context,
- &session->sessionId, session->sessionHandle,
- &request->requestHeader,
- (UA_DeleteRawModifiedDetails*)updateDetailsData,
- &response->results[i]);
- UA_LOCK(server->serviceMutex);
- } else {
+ if(!server->config.historyDatabase.deleteRawModified) {
response->results[i].statusCode = UA_STATUSCODE_BADNOTSUPPORTED;
+ continue;
}
+ UA_UNLOCK(&server->serviceMutex);
+ server->config.historyDatabase.
+ deleteRawModified(server, server->config.historyDatabase.context,
+ &session->sessionId, session->sessionHandle,
+ &request->requestHeader,
+ (UA_DeleteRawModifiedDetails*)updateDetailsData,
+ &response->results[i]);
+ UA_LOCK(&server->serviceMutex);
continue;
}
@@ -36516,21 +39523,21 @@ Service_HistoryUpdate(UA_Server *server, UA_Session *session,
#endif
-UA_StatusCode UA_EXPORT
+UA_StatusCode
UA_Server_writeObjectProperty(UA_Server *server, const UA_NodeId objectId,
const UA_QualifiedName propertyName,
const UA_Variant value) {
- UA_LOCK(server->serviceMutex);
+ UA_LOCK(&server->serviceMutex);
UA_StatusCode retVal = writeObjectProperty(server, objectId, propertyName, value);
- UA_UNLOCK(server->serviceMutex);
+ UA_UNLOCK(&server->serviceMutex);
return retVal;
}
UA_StatusCode
writeObjectProperty(UA_Server *server, const UA_NodeId objectId,
- const UA_QualifiedName propertyName,
- const UA_Variant value) {
- UA_LOCK_ASSERT(server->serviceMutex, 1);
+ const UA_QualifiedName propertyName,
+ const UA_Variant value) {
+ UA_LOCK_ASSERT(&server->serviceMutex, 1);
UA_RelativePathElement rpe;
UA_RelativePathElement_init(&rpe);
rpe.referenceTypeId = UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY);
@@ -36552,8 +39559,8 @@ writeObjectProperty(UA_Server *server, const UA_NodeId objectId,
return retval;
}
- retval = writeWithWriteValue(server, &bpr.targets[0].targetId.nodeId,
- UA_ATTRIBUTEID_VALUE, &UA_TYPES[UA_TYPES_VARIANT], &value);
+ retval = writeValueAttribute(server, &server->adminSession,
+ &bpr.targets[0].targetId.nodeId, &value);
UA_BrowsePathResult_clear(&bpr);
return retval;
@@ -36566,13 +39573,13 @@ UA_Server_writeObjectProperty_scalar(UA_Server *server, const UA_NodeId objectId
UA_Variant var;
UA_Variant_init(&var);
UA_Variant_setScalar(&var, (void*)(uintptr_t)value, type);
- UA_LOCK(server->serviceMutex);
+ UA_LOCK(&server->serviceMutex);
UA_StatusCode retval = writeObjectProperty(server, objectId, propertyName, var);
- UA_UNLOCK(server->serviceMutex);
+ UA_UNLOCK(&server->serviceMutex);
return retval;
}
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/src/server/ua_services_discovery.c" ***********************************/
+/**** amalgamated original file "/src/server/ua_services_discovery.c" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -36689,7 +39696,7 @@ void Service_FindServers(UA_Server *server, UA_Session *session,
const UA_FindServersRequest *request,
UA_FindServersResponse *response) {
UA_LOG_DEBUG_SESSION(&server->config.logger, session, "Processing FindServersRequest");
- UA_LOCK_ASSERT(server->serviceMutex, 1);
+ UA_LOCK_ASSERT(&server->serviceMutex, 1);
/* Return the server itself? */
UA_Boolean foundSelf = false;
@@ -36728,54 +39735,44 @@ void Service_FindServers(UA_Server *server, UA_Session *session,
#else
- /* Temporarily store all the pointers which we found to avoid reiterating
- * through the list */
- size_t foundServersSize = 0;
- UA_STACKARRAY(UA_RegisteredServer*, foundServers, server->discoveryManager.registeredServersSize+1);
+ /* Allocate enough memory, including memory for the "self" response */
+ size_t maxResults = server->discoveryManager.registeredServersSize + 1;
+ response->servers = (UA_ApplicationDescription*)UA_Array_new(maxResults, &UA_TYPES[UA_TYPES_APPLICATIONDESCRIPTION]);
+ if(!response->servers) {
+ response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
+ return;
+ }
+
+ /* Copy into the response. TODO: Evaluate return codes */
+ size_t pos = 0;
+ if(foundSelf)
+ setApplicationDescriptionFromServer(&response->servers[pos++], server);
registeredServer_list_entry* current;
LIST_FOREACH(current, &server->discoveryManager.registeredServers, pointers) {
- if(request->serverUrisSize) {
+ UA_Boolean usable = (request->serverUrisSize == 0);
+ if(!usable) {
/* If client only requested a specific set of servers */
for(size_t i = 0; i < request->serverUrisSize; i++) {
if(UA_String_equal(&current->registeredServer.serverUri, &request->serverUris[i])) {
- foundServers[foundServersSize] = &current->registeredServer;
- foundServersSize++;
+ usable = true;
break;
}
}
- } else {
- /* Return all registered servers */
- foundServers[foundServersSize] = &current->registeredServer;
- foundServersSize++;
}
- }
-
- size_t allocSize = foundServersSize;
- if(foundSelf)
- allocSize++;
-
- /* Nothing to do? */
- if(allocSize == 0)
- return;
- /* Allocate memory */
- response->servers = (UA_ApplicationDescription*)UA_Array_new(allocSize, &UA_TYPES[UA_TYPES_APPLICATIONDESCRIPTION]);
- if(!response->servers) {
- response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
- return;
+ if(usable)
+ setApplicationDescriptionFromRegisteredServer(request, &response->servers[pos++],
+ &current->registeredServer);
}
- response->serversSize = allocSize;
- /* Copy into the response. TODO: Evaluate return codes */
- size_t pos = 0;
- if(foundSelf) {
- setApplicationDescriptionFromServer(&response->servers[pos++], server);
- }
- for(size_t i = 0; i < foundServersSize; i++) {
- setApplicationDescriptionFromRegisteredServer(request, &response->servers[pos++], foundServers[i]);
+ /* Set the final size */
+ if(pos > 0) {
+ response->serversSize = pos;
+ } else {
+ UA_free(response->servers);
+ response->servers = NULL;
}
-
#endif
}
@@ -36783,10 +39780,10 @@ void
Service_GetEndpoints(UA_Server *server, UA_Session *session,
const UA_GetEndpointsRequest *request,
UA_GetEndpointsResponse *response) {
- UA_LOCK_ASSERT(server->serviceMutex, 1);
+ UA_LOCK_ASSERT(&server->serviceMutex, 1);
/* If the client expects to see a specific endpointurl, mirror it back. If
- not, clone the endpoints with the discovery url of all networklayers. */
+ * not, clone the endpoints with the discovery url of all networklayers. */
const UA_String *endpointUrl = &request->endpointUrl;
if(endpointUrl->length > 0) {
UA_LOG_DEBUG_SESSION(&server->config.logger, session,
@@ -36797,33 +39794,6 @@ Service_GetEndpoints(UA_Server *server, UA_Session *session,
"Processing GetEndpointsRequest with an empty endpointUrl");
}
- /* test if the supported binary profile shall be returned */
- size_t reSize = sizeof(UA_Boolean) * server->config.endpointsSize;
- UA_STACKARRAY(UA_Boolean, relevant_endpoints, reSize);
- memset(relevant_endpoints, 0, reSize);
- size_t relevant_count = 0;
- if(request->profileUrisSize == 0) {
- for(size_t j = 0; j < server->config.endpointsSize; ++j)
- relevant_endpoints[j] = true;
- relevant_count = server->config.endpointsSize;
- } else {
- for(size_t j = 0; j < server->config.endpointsSize; ++j) {
- for(size_t i = 0; i < request->profileUrisSize; ++i) {
- if(!UA_String_equal(&request->profileUris[i],
- &server->config.endpoints[j].transportProfileUri))
- continue;
- relevant_endpoints[j] = true;
- ++relevant_count;
- break;
- }
- }
- }
-
- if(relevant_count == 0) {
- response->endpointsSize = 0;
- return;
- }
-
/* Clone the endpoint for each networklayer? */
size_t clone_times = 1;
UA_Boolean nl_endpointurl = false;
@@ -36832,41 +39802,62 @@ Service_GetEndpoints(UA_Server *server, UA_Session *session,
nl_endpointurl = true;
}
- response->endpoints =
- (UA_EndpointDescription*)UA_Array_new(relevant_count * clone_times,
- &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION]);
+ /* Allocate enough memory */
+ response->endpoints = (UA_EndpointDescription*)
+ UA_Array_new(server->config.endpointsSize * clone_times,
+ &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION]);
if(!response->endpoints) {
response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
return;
}
- response->endpointsSize = relevant_count * clone_times;
- size_t k = 0;
- UA_StatusCode retval;
- for(size_t i = 0; i < clone_times; ++i) {
- if(nl_endpointurl)
- endpointUrl = &server->config.networkLayers[i].discoveryUrl;
- for(size_t j = 0; j < server->config.endpointsSize; ++j) {
- if(!relevant_endpoints[j])
- continue;
- retval = UA_EndpointDescription_copy(&server->config.endpoints[j],
- &response->endpoints[k]);
- if(retval != UA_STATUSCODE_GOOD)
- goto error;
- retval = UA_String_copy(endpointUrl, &response->endpoints[k].endpointUrl);
- if(retval != UA_STATUSCODE_GOOD)
- goto error;
- retval = UA_Array_copy(endpointUrl, 1,
- (void**)&response->endpoints[k].server.discoveryUrls,
- &UA_TYPES[UA_TYPES_STRING]);
+ size_t pos = 0;
+ UA_StatusCode retval = UA_STATUSCODE_GOOD;
+ for(size_t j = 0; j < server->config.endpointsSize; ++j) {
+ /* Test if the supported binary profile shall be returned */
+ UA_Boolean usable = (request->profileUrisSize == 0);
+ if(!usable) {
+ for(size_t i = 0; i < request->profileUrisSize; ++i) {
+ if(!UA_String_equal(&request->profileUris[i],
+ &server->config.endpoints[j].transportProfileUri))
+ continue;
+ usable = true;
+ break;
+ }
+ }
+ if(!usable)
+ continue;
+
+ /* Copy into the results */
+ for(size_t i = 0; i < clone_times; ++i) {
+ retval |= UA_EndpointDescription_copy(&server->config.endpoints[j],
+ &response->endpoints[pos]);
+ UA_String_clear(&response->endpoints[pos].endpointUrl);
+ UA_Array_delete(response->endpoints[pos].server.discoveryUrls,
+ response->endpoints[pos].server.discoveryUrlsSize,
+ &UA_TYPES[UA_TYPES_STRING]);
+ response->endpoints[pos].server.discoveryUrls = NULL;
+ response->endpoints[pos].server.discoveryUrlsSize = 0;
+ if(nl_endpointurl)
+ endpointUrl = &server->config.networkLayers[i].discoveryUrl;
+ retval |= UA_String_copy(endpointUrl, &response->endpoints[pos].endpointUrl);
+ retval |= UA_Array_copy(endpointUrl, 1,
+ (void**)&response->endpoints[pos].server.discoveryUrls,
+ &UA_TYPES[UA_TYPES_STRING]);
if(retval != UA_STATUSCODE_GOOD)
goto error;
- response->endpoints[k].server.discoveryUrlsSize = 1;
- ++k;
+ response->endpoints[pos].server.discoveryUrlsSize = 1;
+ pos++;
}
}
- return;
+ UA_assert(pos <= server->config.endpointsSize * clone_times);
+ response->endpointsSize = pos;
+
+ /* Clean up the memory of there are no usable results */
+ if(pos > 0)
+ return;
+
error:
response->responseHeader.serviceResult = retval;
UA_Array_delete(response->endpoints, response->endpointsSize,
@@ -36888,7 +39879,8 @@ process_RegisterServer(UA_Server *server, UA_Session *session,
UA_StatusCode **responseConfigurationResults,
size_t *responseDiagnosticInfosSize,
UA_DiagnosticInfo *responseDiagnosticInfos) {
- UA_LOCK_ASSERT(server->serviceMutex, 1);
+ UA_LOCK_ASSERT(&server->serviceMutex, 1);
+
/* Find the server from the request in the registered list */
registeredServer_list_entry* current;
registeredServer_list_entry *registeredServer_entry = NULL;
@@ -36965,7 +39957,7 @@ process_RegisterServer(UA_Server *server, UA_Session *session,
}
#ifdef UA_ENABLE_DISCOVERY_MULTICAST
- if(server->config.discovery.mdnsEnable) {
+ if(server->config.mdnsEnabled) {
for(size_t i = 0; i < requestServer->discoveryUrlsSize; i++) {
/* create TXT if is online and first index, delete TXT if is offline and last index */
UA_Boolean updateTxt = (requestServer->isOnline && i==0) ||
@@ -36989,24 +39981,18 @@ process_RegisterServer(UA_Server *server, UA_Session *session,
}
if(server->discoveryManager.registerServerCallback) {
- UA_UNLOCK(server->serviceMutex);
+ UA_UNLOCK(&server->serviceMutex);
server->discoveryManager.
registerServerCallback(requestServer,
server->discoveryManager.registerServerCallbackData);
- UA_LOCK(server->serviceMutex);
+ UA_LOCK(&server->serviceMutex);
}
// server found, remove from list
LIST_REMOVE(registeredServer_entry, pointers);
UA_RegisteredServer_clear(&registeredServer_entry->registeredServer);
-#if UA_MULTITHREADING >= 200
- UA_atomic_subSize(&server->discoveryManager.registeredServersSize, 1);
- registeredServer_entry->delayedCleanup.callback = NULL; /* only free the structure */
- UA_WorkQueue_enqueueDelayed(&server->workQueue, &registeredServer_entry->delayedCleanup);
-#else
UA_free(registeredServer_entry);
server->discoveryManager.registeredServersSize--;
-#endif
responseHeader->serviceResult = UA_STATUSCODE_GOOD;
return;
}
@@ -37025,11 +40011,7 @@ process_RegisterServer(UA_Server *server, UA_Session *session,
}
LIST_INSERT_HEAD(&server->discoveryManager.registeredServers, registeredServer_entry, pointers);
-#if UA_MULTITHREADING >= 200
UA_atomic_addSize(&server->discoveryManager.registeredServersSize, 1);
-#else
- server->discoveryManager.registeredServersSize++;
-#endif
} else {
UA_RegisteredServer_clear(&registeredServer_entry->registeredServer);
}
@@ -37039,11 +40021,11 @@ process_RegisterServer(UA_Server *server, UA_Session *session,
// registered before, then crashed, restarts and registeres again. In that case the entry is not deleted
// and the callback would not be called.
if(server->discoveryManager.registerServerCallback) {
- UA_UNLOCK(server->serviceMutex);
+ UA_UNLOCK(&server->serviceMutex);
server->discoveryManager.
registerServerCallback(requestServer,
server->discoveryManager.registerServerCallbackData);
- UA_LOCK(server->serviceMutex)
+ UA_LOCK(&server->serviceMutex);
}
// copy the data from the request into the list
@@ -37057,7 +40039,7 @@ void Service_RegisterServer(UA_Server *server, UA_Session *session,
UA_RegisterServerResponse *response) {
UA_LOG_DEBUG_SESSION(&server->config.logger, session,
"Processing RegisterServerRequest");
- UA_LOCK_ASSERT(server->serviceMutex, 1);
+ UA_LOCK_ASSERT(&server->serviceMutex, 1);
process_RegisterServer(server, session, &request->requestHeader, &request->server, 0,
NULL, &response->responseHeader, 0, NULL, 0, NULL);
}
@@ -37067,7 +40049,7 @@ void Service_RegisterServer2(UA_Server *server, UA_Session *session,
UA_RegisterServer2Response *response) {
UA_LOG_DEBUG_SESSION(&server->config.logger, session,
"Processing RegisterServer2Request");
- UA_LOCK_ASSERT(server->serviceMutex, 1);
+ UA_LOCK_ASSERT(&server->serviceMutex, 1);
process_RegisterServer(server, session, &request->requestHeader, &request->server,
request->discoveryConfigurationSize, request->discoveryConfiguration,
&response->responseHeader, &response->configurationResultsSize,
@@ -37083,8 +40065,8 @@ void UA_Discovery_cleanupTimedOut(UA_Server *server, UA_DateTime nowMonotonic) {
UA_DateTime timedOut = nowMonotonic;
// registration is timed out if lastSeen is older than 60 minutes (default
// value, can be modified by user).
- if(server->config.discovery.cleanupTimeout)
- timedOut -= server->config.discovery.cleanupTimeout*UA_DATETIME_SEC;
+ if(server->config.discoveryCleanupTimeout)
+ timedOut -= server->config.discoveryCleanupTimeout * UA_DATETIME_SEC;
registeredServer_list_entry* current, *temp;
LIST_FOREACH_SAFE(current, &server->discoveryManager.registeredServers, pointers, temp) {
@@ -37108,7 +40090,7 @@ void UA_Discovery_cleanupTimedOut(UA_Server *server, UA_DateTime nowMonotonic) {
}
#endif
- if(semaphoreDeleted || (server->config.discovery.cleanupTimeout &&
+ if(semaphoreDeleted || (server->config.discoveryCleanupTimeout &&
current->lastSeen < timedOut)) {
if(semaphoreDeleted) {
UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_SERVER,
@@ -37127,14 +40109,8 @@ void UA_Discovery_cleanupTimedOut(UA_Server *server, UA_DateTime nowMonotonic) {
}
LIST_REMOVE(current, pointers);
UA_RegisteredServer_clear(&current->registeredServer);
-#if UA_MULTITHREADING >= 200
- UA_atomic_subSize(&server->discoveryManager.registeredServersSize, 1);
- current->delayedCleanup.callback = NULL; /* Only free the structure */
- UA_WorkQueue_enqueueDelayed(&server->workQueue, &current->delayedCleanup);
-#else
UA_free(current);
server->discoveryManager.registeredServersSize--;
-#endif
}
}
}
@@ -37151,7 +40127,7 @@ void UA_Discovery_cleanupTimedOut(UA_Server *server, UA_DateTime nowMonotonic) {
static void
periodicServerRegister(UA_Server *server, void *data) {
UA_assert(data != NULL);
- UA_LOCK(server->serviceMutex);
+ UA_LOCK(&server->serviceMutex);
struct PeriodicServerRegisterCallback *cb = (struct PeriodicServerRegisterCallback *)data;
@@ -37196,7 +40172,7 @@ periodicServerRegister(UA_Server *server, void *data) {
cb->this_interval = nextInterval;
changeRepeatedCallbackInterval(server, cb->id, nextInterval);
- UA_UNLOCK(server->serviceMutex);
+ UA_UNLOCK(&server->serviceMutex);
return;
}
@@ -37211,7 +40187,7 @@ periodicServerRegister(UA_Server *server, void *data) {
if(retval == UA_STATUSCODE_GOOD)
cb->registered = true;
}
- UA_UNLOCK(server->serviceMutex);
+ UA_UNLOCK(&server->serviceMutex);
}
UA_StatusCode
@@ -37221,18 +40197,18 @@ UA_Server_addPeriodicServerRegisterCallback(UA_Server *server,
UA_Double intervalMs,
UA_Double delayFirstRegisterMs,
UA_UInt64 *periodicCallbackId) {
- UA_LOCK(server->serviceMutex);
+ UA_LOCK(&server->serviceMutex);
/* No valid server URL */
if(!discoveryServerUrl) {
UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
"No discovery server URL provided");
- UA_UNLOCK(server->serviceMutex);
+ UA_UNLOCK(&server->serviceMutex);
return UA_STATUSCODE_BADINTERNALERROR;
}
if (client->connection.state != UA_CONNECTIONSTATE_CLOSED) {
- UA_UNLOCK(server->serviceMutex);
+ UA_UNLOCK(&server->serviceMutex);
return UA_STATUSCODE_BADINVALIDSTATE;
}
@@ -37258,7 +40234,7 @@ UA_Server_addPeriodicServerRegisterCallback(UA_Server *server,
struct PeriodicServerRegisterCallback* cb = (struct PeriodicServerRegisterCallback*)
UA_malloc(sizeof(struct PeriodicServerRegisterCallback));
if(!cb) {
- UA_UNLOCK(server->serviceMutex);
+ UA_UNLOCK(&server->serviceMutex);
return UA_STATUSCODE_BADOUTOFMEMORY;
}
@@ -37273,7 +40249,7 @@ UA_Server_addPeriodicServerRegisterCallback(UA_Server *server,
cb->discovery_server_url = (char*)UA_malloc(len+1);
if (!cb->discovery_server_url) {
UA_free(cb);
- UA_UNLOCK(server->serviceMutex);
+ UA_UNLOCK(&server->serviceMutex);
return UA_STATUSCODE_BADOUTOFMEMORY;
}
memcpy(cb->discovery_server_url, discoveryServerUrl, len+1);
@@ -37287,7 +40263,7 @@ UA_Server_addPeriodicServerRegisterCallback(UA_Server *server,
"Could not create periodic job for server register. "
"StatusCode %s", UA_StatusCode_name(retval));
UA_free(cb);
- UA_UNLOCK(server->serviceMutex);
+ UA_UNLOCK(&server->serviceMutex);
return retval;
}
@@ -37298,7 +40274,7 @@ UA_Server_addPeriodicServerRegisterCallback(UA_Server *server,
if(!newEntry) {
removeCallback(server, cb->id);
UA_free(cb);
- UA_UNLOCK(server->serviceMutex);
+ UA_UNLOCK(&server->serviceMutex);
return UA_STATUSCODE_BADOUTOFMEMORY;
}
newEntry->callback = cb;
@@ -37307,7 +40283,7 @@ UA_Server_addPeriodicServerRegisterCallback(UA_Server *server,
if(periodicCallbackId)
*periodicCallbackId = cb->id;
- UA_UNLOCK(server->serviceMutex);
+ UA_UNLOCK(&server->serviceMutex);
return UA_STATUSCODE_GOOD;
}
@@ -37315,21 +40291,21 @@ void
UA_Server_setRegisterServerCallback(UA_Server *server,
UA_Server_registerServerCallback cb,
void* data) {
- UA_LOCK(server->serviceMutex);
+ UA_LOCK(&server->serviceMutex);
server->discoveryManager.registerServerCallback = cb;
server->discoveryManager.registerServerCallbackData = data;
- UA_UNLOCK(server->serviceMutex);
+ UA_UNLOCK(&server->serviceMutex);
}
#endif /* UA_ENABLE_DISCOVERY */
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/src/server/ua_services_subscription.c" ***********************************/
+/**** amalgamated original file "/src/server/ua_services_subscription.c" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
- * Copyright 2014-2018 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
+ * Copyright 2014-2018, 2022 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
* Copyright 2016-2017 (c) Florian Palm
* Copyright 2015 (c) Chris Iatrou
* Copyright 2015-2016 (c) Sten Grüner
@@ -37346,20 +40322,34 @@ UA_Server_setRegisterServerCallback(UA_Server *server,
#ifdef UA_ENABLE_SUBSCRIPTIONS /* conditional compilation */
-static UA_StatusCode
+static void
+setPublishingEnabled(UA_Subscription *sub, UA_Boolean publishingEnabled) {
+ if(sub->publishingEnabled == publishingEnabled)
+ return;
+
+ sub->publishingEnabled = publishingEnabled;
+
+#ifdef UA_ENABLE_DIAGNOSTICS
+ if(publishingEnabled)
+ sub->enableCount++;
+ else
+ sub->disableCount++;
+#endif
+}
+
+static void
setSubscriptionSettings(UA_Server *server, UA_Subscription *subscription,
UA_Double requestedPublishingInterval,
UA_UInt32 requestedLifetimeCount,
UA_UInt32 requestedMaxKeepAliveCount,
- UA_UInt32 maxNotificationsPerPublish, UA_Byte priority) {
- UA_LOCK_ASSERT(server->serviceMutex, 1);
-
- /* deregister the callback if required */
- Subscription_unregisterPublishCallback(server, subscription);
+ UA_UInt32 maxNotificationsPerPublish,
+ UA_Byte priority) {
+ UA_LOCK_ASSERT(&server->serviceMutex, 1);
/* re-parameterize the subscription */
UA_BOUNDEDVALUE_SETWBOUNDS(server->config.publishingIntervalLimits,
- requestedPublishingInterval, subscription->publishingInterval);
+ requestedPublishingInterval,
+ subscription->publishingInterval);
/* check for nan*/
if(requestedPublishingInterval != requestedPublishingInterval)
subscription->publishingInterval = server->config.publishingIntervalLimits.min;
@@ -37374,72 +40364,89 @@ setSubscriptionSettings(UA_Server *server, UA_Subscription *subscription,
maxNotificationsPerPublish > server->config.maxNotificationsPerPublish)
subscription->notificationsPerPublish = server->config.maxNotificationsPerPublish;
subscription->priority = priority;
-
- UA_StatusCode retval = Subscription_registerPublishCallback(server, subscription);
- if(retval != UA_STATUSCODE_GOOD) {
- UA_LOG_DEBUG_SESSION(&server->config.logger, subscription->session,
- "Subscription %" PRIu32 " | Could not register publish callback with error code %s",
- subscription->subscriptionId, UA_StatusCode_name(retval));
- }
- return retval;
}
void
Service_CreateSubscription(UA_Server *server, UA_Session *session,
const UA_CreateSubscriptionRequest *request,
UA_CreateSubscriptionResponse *response) {
- UA_LOCK_ASSERT(server->serviceMutex, 1);
+ UA_LOCK_ASSERT(&server->serviceMutex, 1);
/* Check limits for the number of subscriptions */
if(((server->config.maxSubscriptions != 0) &&
- (server->numSubscriptions >= server->config.maxSubscriptions)) ||
+ (server->subscriptionsSize >= server->config.maxSubscriptions)) ||
((server->config.maxSubscriptionsPerSession != 0) &&
- (session->numSubscriptions >= server->config.maxSubscriptionsPerSession))) {
+ (session->subscriptionsSize >= server->config.maxSubscriptionsPerSession))) {
response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYSUBSCRIPTIONS;
return;
}
/* Create the subscription */
- UA_Subscription *newSubscription = UA_Subscription_new(session, response->subscriptionId);
- if(!newSubscription) {
+ UA_Subscription *sub= UA_Subscription_new();
+ if(!sub) {
UA_LOG_DEBUG_SESSION(&server->config.logger, session,
"Processing CreateSubscriptionRequest failed");
response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
return;
}
- UA_Session_addSubscription(server, session, newSubscription); /* Also assigns the subscription id */
-
/* Set the subscription parameters */
- newSubscription->publishingEnabled = request->publishingEnabled;
- UA_StatusCode retval = setSubscriptionSettings(server, newSubscription, request->requestedPublishingInterval,
- request->requestedLifetimeCount, request->requestedMaxKeepAliveCount,
- request->maxNotificationsPerPublish, request->priority);
-
+ setSubscriptionSettings(server, sub, request->requestedPublishingInterval,
+ request->requestedLifetimeCount,
+ request->requestedMaxKeepAliveCount,
+ request->maxNotificationsPerPublish, request->priority);
+ setPublishingEnabled(sub, request->publishingEnabled);
+ sub->currentKeepAliveCount = sub->maxKeepAliveCount; /* set settings first */
+
+ /* Assign the SubscriptionId */
+ sub->subscriptionId = ++server->lastSubscriptionId;
+
+ /* Register the cyclic callback */
+ UA_StatusCode retval = Subscription_registerPublishCallback(server, sub);
if(retval != UA_STATUSCODE_GOOD) {
+ UA_LOG_DEBUG_SESSION(&server->config.logger, sub->session,
+ "Subscription %" PRIu32 " | "
+ "Could not register publish callback with error code %s",
+ sub->subscriptionId, UA_StatusCode_name(retval));
response->responseHeader.serviceResult = retval;
+ UA_Subscription_delete(server, sub);
return;
}
- newSubscription->currentKeepAliveCount = newSubscription->maxKeepAliveCount; /* set settings first */
+ /* Register the subscription in the server */
+ LIST_INSERT_HEAD(&server->subscriptions, sub, serverListEntry);
+ server->subscriptionsSize++;
+
+ /* Update the server statistics */
+ server->serverDiagnosticsSummary.currentSubscriptionCount++;
+ server->serverDiagnosticsSummary.cumulatedSubscriptionCount++;
+
+ /* Attach the Subscription to the session */
+ UA_Session_attachSubscription(session, sub);
/* Prepare the response */
- response->subscriptionId = newSubscription->subscriptionId;
- response->revisedPublishingInterval = newSubscription->publishingInterval;
- response->revisedLifetimeCount = newSubscription->lifeTimeCount;
- response->revisedMaxKeepAliveCount = newSubscription->maxKeepAliveCount;
+ response->subscriptionId = sub->subscriptionId;
+ response->revisedPublishingInterval = sub->publishingInterval;
+ response->revisedLifetimeCount = sub->lifeTimeCount;
+ response->revisedMaxKeepAliveCount = sub->maxKeepAliveCount;
- UA_LOG_INFO_SESSION(&server->config.logger, session, "Subscription %" PRIu32 " | "
- "Created the Subscription with a publishing interval of %.2f ms",
- response->subscriptionId, newSubscription->publishingInterval);
-}
+#ifdef UA_ENABLE_DIAGNOSTICS
+ createSubscriptionObject(server, session, sub);
+#endif
+
+ UA_LOG_INFO_SUBSCRIPTION(&server->config.logger, sub,
+ "Subscription created (Publishing interval %.2fms, "
+ "max %lu notifications per publish)",
+ sub->publishingInterval,
+ (long unsigned)sub->notificationsPerPublish);}
void
Service_ModifySubscription(UA_Server *server, UA_Session *session,
const UA_ModifySubscriptionRequest *request,
UA_ModifySubscriptionResponse *response) {
- UA_LOG_DEBUG_SESSION(&server->config.logger, session, "Processing ModifySubscriptionRequest");
- UA_LOCK_ASSERT(server->serviceMutex, 1);
+ UA_LOG_DEBUG_SESSION(&server->config.logger, session,
+ "Processing ModifySubscriptionRequest");
+ UA_LOCK_ASSERT(&server->serviceMutex, 1);
UA_Subscription *sub = UA_Session_getSubscriptionById(session, request->subscriptionId);
if(!sub) {
@@ -37447,26 +40454,50 @@ Service_ModifySubscription(UA_Server *server, UA_Session *session,
return;
}
- UA_StatusCode retval = setSubscriptionSettings(server, sub, request->requestedPublishingInterval,
- request->requestedLifetimeCount, request->requestedMaxKeepAliveCount,
- request->maxNotificationsPerPublish, request->priority);
+ /* Store the old publishing interval */
+ UA_Double oldPublishingInterval = sub->publishingInterval;
+ UA_Byte oldPriority = sub->priority;
- if(retval != UA_STATUSCODE_GOOD) {
- response->responseHeader.serviceResult = retval;
- return;
+ /* Change the Subscription settings */
+ setSubscriptionSettings(server, sub, request->requestedPublishingInterval,
+ request->requestedLifetimeCount,
+ request->requestedMaxKeepAliveCount,
+ request->maxNotificationsPerPublish, request->priority);
+
+ /* Reset the subscription lifetime */
+ sub->currentLifetimeCount = 0;
+
+ /* Change the repeated callback to the new interval. This cannot fail as the
+ * CallbackId must exist. */
+ if(sub->publishCallbackId > 0 &&
+ sub->publishingInterval != oldPublishingInterval)
+ changeRepeatedCallbackInterval(server, sub->publishCallbackId,
+ sub->publishingInterval);
+
+ /* If the priority has changed, re-enter the subscription to the
+ * priority-ordered queue in the session. */
+ if(oldPriority != sub->priority) {
+ UA_Session_detachSubscription(server, session, sub, false);
+ UA_Session_attachSubscription(session, sub);
}
- sub->currentLifetimeCount = 0; /* Reset the subscription lifetime */
+ /* Set the response */
response->revisedPublishingInterval = sub->publishingInterval;
response->revisedLifetimeCount = sub->lifeTimeCount;
response->revisedMaxKeepAliveCount = sub->maxKeepAliveCount;
+
+ /* Update the diagnostics statistics */
+#ifdef UA_ENABLE_DIAGNOSTICS
+ sub->modifyCount++;
+#endif
}
static void
Operation_SetPublishingMode(UA_Server *server, UA_Session *session,
- const UA_Boolean *publishingEnabled, const UA_UInt32 *subscriptionId,
+ const UA_Boolean *publishingEnabled,
+ const UA_UInt32 *subscriptionId,
UA_StatusCode *result) {
- UA_LOCK_ASSERT(server->serviceMutex, 1);
+ UA_LOCK_ASSERT(&server->serviceMutex, 1);
UA_Subscription *sub = UA_Session_getSubscriptionById(session, *subscriptionId);
if(!sub) {
*result = UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
@@ -37474,46 +40505,52 @@ Operation_SetPublishingMode(UA_Server *server, UA_Session *session,
}
sub->currentLifetimeCount = 0; /* Reset the subscription lifetime */
- sub->publishingEnabled = *publishingEnabled; /* Set the publishing mode */
+ setPublishingEnabled(sub, *publishingEnabled); /* Set the publishing mode */
}
void
Service_SetPublishingMode(UA_Server *server, UA_Session *session,
const UA_SetPublishingModeRequest *request,
UA_SetPublishingModeResponse *response) {
- UA_LOG_DEBUG_SESSION(&server->config.logger, session, "Processing SetPublishingModeRequest");
- UA_LOCK_ASSERT(server->serviceMutex, 1);
+ UA_LOG_DEBUG_SESSION(&server->config.logger, session,
+ "Processing SetPublishingModeRequest");
+ UA_LOCK_ASSERT(&server->serviceMutex, 1);
UA_Boolean publishingEnabled = request->publishingEnabled; /* request is const */
response->responseHeader.serviceResult =
- UA_Server_processServiceOperations(server, session, (UA_ServiceOperation)Operation_SetPublishingMode,
+ UA_Server_processServiceOperations(server, session,
+ (UA_ServiceOperation)Operation_SetPublishingMode,
&publishingEnabled,
- &request->subscriptionIdsSize, &UA_TYPES[UA_TYPES_UINT32],
- &response->resultsSize, &UA_TYPES[UA_TYPES_STATUSCODE]);
+ &request->subscriptionIdsSize,
+ &UA_TYPES[UA_TYPES_UINT32],
+ &response->resultsSize,
+ &UA_TYPES[UA_TYPES_STATUSCODE]);
}
-void
+UA_StatusCode
Service_Publish(UA_Server *server, UA_Session *session,
const UA_PublishRequest *request, UA_UInt32 requestId) {
UA_LOG_DEBUG_SESSION(&server->config.logger, session, "Processing PublishRequest");
- UA_LOCK_ASSERT(server->serviceMutex, 1);
+ UA_LOCK_ASSERT(&server->serviceMutex, 1);
/* Return an error if the session has no subscription */
- if(LIST_EMPTY(&session->serverSubscriptions)) {
- sendServiceFault(session->header.channel, requestId, request->requestHeader.requestHandle,
- &UA_TYPES[UA_TYPES_PUBLISHRESPONSE], UA_STATUSCODE_BADNOSUBSCRIPTION);
- return;
+ if(TAILQ_EMPTY(&session->subscriptions)) {
+ sendServiceFault(session->header.channel, requestId,
+ request->requestHeader.requestHandle,
+ UA_STATUSCODE_BADNOSUBSCRIPTION);
+ return UA_STATUSCODE_BADNOSUBSCRIPTION;
}
/* Handle too many subscriptions to free resources before trying to allocate
* resources for the new publish request. If the limit has been reached the
* oldest publish request shall be responded */
if((server->config.maxPublishReqPerSession != 0) &&
- (session->numPublishReq >= server->config.maxPublishReqPerSession)) {
- if(!UA_Subscription_reachedPublishReqLimit(server, session)) {
- sendServiceFault(session->header.channel, requestId, request->requestHeader.requestHandle,
- &UA_TYPES[UA_TYPES_PUBLISHRESPONSE], UA_STATUSCODE_BADINTERNALERROR);
- return;
+ (session->responseQueueSize >= server->config.maxPublishReqPerSession)) {
+ if(!UA_Session_reachedPublishReqLimit(server, session)) {
+ sendServiceFault(session->header.channel, requestId,
+ request->requestHeader.requestHandle,
+ UA_STATUSCODE_BADINTERNALERROR);
+ return UA_STATUSCODE_BADINTERNALERROR;
}
}
@@ -37521,9 +40558,10 @@ Service_Publish(UA_Server *server, UA_Session *session,
UA_PublishResponseEntry *entry = (UA_PublishResponseEntry *)
UA_malloc(sizeof(UA_PublishResponseEntry));
if(!entry) {
- sendServiceFault(session->header.channel, requestId, request->requestHeader.requestHandle,
- &UA_TYPES[UA_TYPES_PUBLISHRESPONSE], UA_STATUSCODE_BADOUTOFMEMORY);
- return;
+ sendServiceFault(session->header.channel, requestId,
+ request->requestHeader.requestHandle,
+ UA_STATUSCODE_BADOUTOFMEMORY);
+ return UA_STATUSCODE_BADOUTOFMEMORY;
}
/* Prepare the response */
@@ -37539,13 +40577,16 @@ Service_Publish(UA_Server *server, UA_Session *session,
&UA_TYPES[UA_TYPES_STATUSCODE]);
if(!response->results) {
UA_free(entry);
- sendServiceFault(session->header.channel, requestId, request->requestHeader.requestHandle,
- &UA_TYPES[UA_TYPES_PUBLISHRESPONSE], UA_STATUSCODE_BADOUTOFMEMORY);
- return;
+ sendServiceFault(session->header.channel, requestId,
+ request->requestHeader.requestHandle,
+ UA_STATUSCODE_BADOUTOFMEMORY);
+ return UA_STATUSCODE_BADOUTOFMEMORY;
}
response->resultsSize = request->subscriptionAcknowledgementsSize;
}
+ /* <--- A good StatusCode is returned from here on ---> */
+
/* Delete Acknowledged Subscription Messages */
for(size_t i = 0; i < request->subscriptionAcknowledgementsSize; ++i) {
UA_SubscriptionAcknowledgement *ack = &request->subscriptionAcknowledgements[i];
@@ -37558,7 +40599,8 @@ Service_Publish(UA_Server *server, UA_Session *session,
continue;
}
/* Remove the acked transmission from the retransmission queue */
- response->results[i] = UA_Subscription_removeRetransmissionMessage(sub, ack->sequenceNumber);
+ response->results[i] =
+ UA_Subscription_removeRetransmissionMessage(sub, ack->sequenceNumber);
}
/* Queue the publish response. It will be dequeued in a repeated publish
@@ -37568,65 +40610,60 @@ Service_Publish(UA_Server *server, UA_Session *session,
UA_LOG_DEBUG_SESSION(&server->config.logger, session, "Queued a publication message");
/* If there are late subscriptions, the new publish request is used to
- * answer them immediately. However, a single subscription that generates
- * many notifications must not "starve" other late subscriptions. Therefore
- * we keep track of the last subscription that got preferential treatment.
- * We start searching for late subscriptions **after** the last one. */
-
- UA_Subscription *immediate = NULL;
- if(session->lastSeenSubscriptionId > 0) {
- LIST_FOREACH(immediate, &session->serverSubscriptions, listEntry) {
- if(immediate->subscriptionId == session->lastSeenSubscriptionId) {
- immediate = LIST_NEXT(immediate, listEntry);
- break;
- }
- }
- }
+ * answer them immediately. Late subscriptions with higher priority are
+ * considered earlier. However, a single subscription that generates many
+ * notifications must not "starve" other late subscriptions. Hence we move
+ * it to the end of the queue for the subscriptions of that priority. */
+ UA_Subscription *late = NULL;
+ TAILQ_FOREACH(late, &session->subscriptions, sessionListEntry) {
+ if(late->state != UA_SUBSCRIPTIONSTATE_LATE)
+ continue;
- /* If no entry was found, start at the beginning and don't restart */
- UA_Boolean found = false;
- if(!immediate)
- immediate = LIST_FIRST(&session->serverSubscriptions);
- else
- found = true;
+ UA_LOG_DEBUG_SUBSCRIPTION(&server->config.logger, late,
+ "Send PublishResponse on a late subscription");
+ UA_Subscription_publish(server, late);
- repeat:
- while(immediate) {
- if(immediate->state == UA_SUBSCRIPTIONSTATE_LATE) {
- session->lastSeenSubscriptionId = immediate->subscriptionId;
- UA_LOG_DEBUG_SESSION(&server->config.logger, session,
- "Subscription %" PRIu32 " | Response on a late subscription",
- immediate->subscriptionId);
- UA_Subscription_publish(server, immediate);
- return;
- }
- immediate = LIST_NEXT(immediate, listEntry);
- }
+ /* The subscription was detached from the session during publish? */
+ if(!late->session)
+ break;
- /* Restart at the beginning of the list */
- if(found) {
- immediate = LIST_FIRST(&session->serverSubscriptions);
- found = false;
- goto repeat;
+ /* Find the first element with smaller priority. If there is none,
+ * insert at the end. */
+ UA_Subscription *after = TAILQ_NEXT(late, sessionListEntry);
+ while(after && after->priority >= late->priority)
+ after = TAILQ_NEXT(after, sessionListEntry);
+
+ TAILQ_REMOVE(&session->subscriptions, late, sessionListEntry);
+
+ if(after)
+ TAILQ_INSERT_BEFORE(after, late, sessionListEntry);
+ else
+ TAILQ_INSERT_TAIL(&session->subscriptions, late, sessionListEntry);
+
+ break;
}
- /* No late subscription this time */
- session->lastSeenSubscriptionId = 0;
+ return UA_STATUSCODE_GOOD;
}
static void
Operation_DeleteSubscription(UA_Server *server, UA_Session *session, void *_,
const UA_UInt32 *subscriptionId, UA_StatusCode *result) {
- *result = UA_Session_deleteSubscription(server, session, *subscriptionId);
- if(*result == UA_STATUSCODE_GOOD) {
- UA_LOG_DEBUG_SESSION(&server->config.logger, session,
- "Subscription %" PRIu32 " | Subscription deleted",
- *subscriptionId);
- } else {
+ UA_Subscription *sub = UA_Session_getSubscriptionById(session, *subscriptionId);
+ if(!sub) {
+ *result = UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
UA_LOG_DEBUG_SESSION(&server->config.logger, session,
- "Deleting Subscription with Id %" PRIu32 " failed with error code %s",
+ "Deleting Subscription with Id %" PRIu32
+ " failed with error code %s",
*subscriptionId, UA_StatusCode_name(*result));
+ return;
}
+
+ UA_Subscription_delete(server, sub);
+ *result = UA_STATUSCODE_GOOD;
+ UA_LOG_DEBUG_SESSION(&server->config.logger, session,
+ "Subscription %" PRIu32 " | Subscription deleted",
+ *subscriptionId);
}
void
@@ -37635,20 +40672,13 @@ Service_DeleteSubscriptions(UA_Server *server, UA_Session *session,
UA_DeleteSubscriptionsResponse *response) {
UA_LOG_DEBUG_SESSION(&server->config.logger, session,
"Processing DeleteSubscriptionsRequest");
- UA_LOCK_ASSERT(server->serviceMutex, 1);
+ UA_LOCK_ASSERT(&server->serviceMutex, 1);
response->responseHeader.serviceResult =
UA_Server_processServiceOperations(server, session,
(UA_ServiceOperation)Operation_DeleteSubscription, NULL,
&request->subscriptionIdsSize, &UA_TYPES[UA_TYPES_UINT32],
&response->resultsSize, &UA_TYPES[UA_TYPES_STATUSCODE]);
-
- /* The session has at least one subscription */
- if(LIST_FIRST(&session->serverSubscriptions))
- return;
-
- /* Send remaining publish responses if the last subscription was removed */
- UA_Subscription_answerPublishRequestsNoSubscription(server, session);
}
void
@@ -37657,7 +40687,7 @@ Service_Republish(UA_Server *server, UA_Session *session,
UA_RepublishResponse *response) {
UA_LOG_DEBUG_SESSION(&server->config.logger, session,
"Processing RepublishRequest");
- UA_LOCK_ASSERT(server->serviceMutex, 1);
+ UA_LOCK_ASSERT(&server->serviceMutex, 1);
/* Get the subscription */
UA_Subscription *sub = UA_Session_getSubscriptionById(session, request->subscriptionId);
@@ -37669,6 +40699,11 @@ Service_Republish(UA_Server *server, UA_Session *session,
/* Reset the subscription lifetime */
sub->currentLifetimeCount = 0;
+ /* Update the subscription statistics */
+#ifdef UA_ENABLE_DIAGNOSTICS
+ sub->republishRequestCount++;
+#endif
+
/* Find the notification in the retransmission queue */
UA_NotificationMessageEntry *entry;
TAILQ_FOREACH(entry, &sub->retransmissionQueue, listEntry) {
@@ -37682,11 +40717,227 @@ Service_Republish(UA_Server *server, UA_Session *session,
response->responseHeader.serviceResult =
UA_NotificationMessage_copy(&entry->message, &response->notificationMessage);
+
+ /* Update the subscription statistics for the case where we return a message */
+#ifdef UA_ENABLE_DIAGNOSTICS
+ sub->republishMessageCount++;
+#endif
+}
+
+static UA_StatusCode
+setTransferredSequenceNumbers(const UA_Subscription *sub, UA_TransferResult *result) {
+ /* Allocate memory */
+ result->availableSequenceNumbers = (UA_UInt32*)
+ UA_Array_new(sub->retransmissionQueueSize, &UA_TYPES[UA_TYPES_UINT32]);
+ if(!result->availableSequenceNumbers)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ result->availableSequenceNumbersSize = sub->retransmissionQueueSize;
+
+ /* Copy over the sequence numbers */
+ UA_NotificationMessageEntry *entry;
+ size_t i = 0;
+ TAILQ_FOREACH(entry, &sub->retransmissionQueue, listEntry) {
+ result->availableSequenceNumbers[i] = entry->message.sequenceNumber;
+ i++;
+ }
+
+ UA_assert(i == result->availableSequenceNumbersSize);
+
+ return UA_STATUSCODE_GOOD;
+}
+
+static void
+Operation_TransferSubscription(UA_Server *server, UA_Session *session,
+ const UA_Boolean *sendInitialValues,
+ const UA_UInt32 *subscriptionId,
+ UA_TransferResult *result) {
+ /* Get the subscription. This requires a server-wide lookup instead of the
+ * usual session-wide lookup. */
+ UA_Subscription *sub = UA_Server_getSubscriptionById(server, *subscriptionId);
+ if(!sub) {
+ result->statusCode = UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
+ return;
+ }
+
+ /* Update the diagnostics statistics */
+#ifdef UA_ENABLE_DIAGNOSTICS
+ sub->transferRequestCount++;
+#endif
+
+ /* Is this the same session? Return the sequence numbers and do nothing else. */
+ UA_Session *oldSession = sub->session;
+ if(oldSession == session) {
+ result->statusCode = setTransferredSequenceNumbers(sub, result);
+#ifdef UA_ENABLE_DIAGNOSTICS
+ sub->transferredToSameClientCount++;
+#endif
+ return;
+ }
+
+ /* Check with AccessControl if the transfer is allowed */
+ if(!server->config.accessControl.allowTransferSubscription ||
+ !server->config.accessControl.
+ allowTransferSubscription(server, &server->config.accessControl,
+ oldSession ? &oldSession->sessionId : NULL,
+ oldSession ? oldSession->sessionHandle : NULL,
+ &session->sessionId, session->sessionHandle)) {
+ result->statusCode = UA_STATUSCODE_BADUSERACCESSDENIED;
+ return;
+ }
+
+ /* Check limits for the number of subscriptions for this Session */
+ if((server->config.maxSubscriptionsPerSession != 0) &&
+ (session->subscriptionsSize >= server->config.maxSubscriptionsPerSession)) {
+ result->statusCode = UA_STATUSCODE_BADTOOMANYSUBSCRIPTIONS;
+ return;
+ }
+
+ /* Allocate memory for the new subscription */
+ UA_Subscription *newSub = (UA_Subscription*)UA_malloc(sizeof(UA_Subscription));
+ if(!newSub) {
+ result->statusCode = UA_STATUSCODE_BADOUTOFMEMORY;
+ return;
+ }
+
+ /* Set the available sequence numbers */
+ result->statusCode = setTransferredSequenceNumbers(sub, result);
+ if(result->statusCode != UA_STATUSCODE_GOOD) {
+ UA_free(newSub);
+ return;
+ }
+
+ /* Create an identical copy of the Subscription struct. The original
+ * subscription remains in place until a StatusChange notification has been
+ * sent. The elements for lists and queues are moved over manually to ensure
+ * that all backpointers are set correctly. */
+ memcpy(newSub, sub, sizeof(UA_Subscription));
+
+ /* Register cyclic publish callback */
+ result->statusCode = Subscription_registerPublishCallback(server, newSub);
+ if(result->statusCode != UA_STATUSCODE_GOOD) {
+ UA_Array_delete(result->availableSequenceNumbers,
+ sub->retransmissionQueueSize, &UA_TYPES[UA_TYPES_UINT32]);
+ result->availableSequenceNumbers = NULL;
+ result->availableSequenceNumbersSize = 0;
+ UA_free(newSub);
+ return;
+ }
+
+ /* <-- The point of no return --> */
+
+ /* Move over the MonitoredItems and adjust the backpointers */
+ LIST_INIT(&newSub->monitoredItems);
+ UA_MonitoredItem *mon, *mon_tmp;
+ LIST_FOREACH_SAFE(mon, &sub->monitoredItems, listEntry, mon_tmp) {
+ LIST_REMOVE(mon, listEntry);
+ mon->subscription = newSub;
+ LIST_INSERT_HEAD(&newSub->monitoredItems, mon, listEntry);
+ }
+ sub->monitoredItemsSize = 0;
+
+ /* Move over the notification queue */
+ TAILQ_INIT(&newSub->notificationQueue);
+ UA_Notification *nn;
+ TAILQ_FOREACH(nn, &sub->notificationQueue, globalEntry) {
+ TAILQ_REMOVE(&sub->notificationQueue, nn, globalEntry);
+ TAILQ_INSERT_TAIL(&newSub->notificationQueue, nn, globalEntry);
+ }
+ sub->notificationQueueSize = 0;
+ sub->dataChangeNotifications = 0;
+ sub->eventNotifications = 0;
+
+ TAILQ_INIT(&newSub->retransmissionQueue);
+ UA_NotificationMessageEntry *nme, *nme_tmp;
+ TAILQ_FOREACH_SAFE(nme, &sub->retransmissionQueue, listEntry, nme_tmp) {
+ TAILQ_REMOVE(&sub->retransmissionQueue, nme, listEntry);
+ TAILQ_INSERT_TAIL(&newSub->retransmissionQueue, nme, listEntry);
+ if(oldSession)
+ oldSession->totalRetransmissionQueueSize -= 1;
+ sub->retransmissionQueueSize -= 1;
+ }
+ UA_assert(sub->retransmissionQueueSize == 0);
+ sub->retransmissionQueueSize = 0;
+
+ /* Add to the server */
+ UA_assert(newSub->subscriptionId == sub->subscriptionId);
+ LIST_INSERT_HEAD(&server->subscriptions, newSub, serverListEntry);
+ server->subscriptionsSize++;
+
+ /* Attach to the session */
+ UA_Session_attachSubscription(session, newSub);
+
+ UA_LOG_INFO_SUBSCRIPTION(&server->config.logger, newSub, "Transferred to this Session");
+
+ /* Set StatusChange in the original subscription and force publish. This
+ * also removes the Subscription, even if there was no PublishResponse
+ * queued to send a StatusChangeNotification. */
+ sub->statusChange = UA_STATUSCODE_GOODSUBSCRIPTIONTRANSFERRED;
+ UA_Subscription_publish(server, sub);
+ UA_assert(sub->publishCallbackId == 0);
+
+ /* Create notifications with the current values */
+ if(*sendInitialValues) {
+ LIST_FOREACH(mon, &newSub->monitoredItems, listEntry) {
+
+ /* Create only DataChange notifications */
+ if(mon->itemToMonitor.attributeId == UA_ATTRIBUTEID_EVENTNOTIFIER)
+ continue;
+
+ /* Only if the mode is monitoring */
+ if(mon->monitoringMode != UA_MONITORINGMODE_REPORTING)
+ continue;
+
+ /* If a value is queued for a data MonitoredItem, the next value in
+ * the queue is sent in the Publish response. */
+ if(mon->queueSize > 0)
+ continue;
+
+ /* Create a notification with the last sampled value */
+ UA_MonitoredItem_createDataChangeNotification(server, newSub, mon,
+ &mon->lastValue);
+ }
+ }
+
+ /* Do not update the statistics for the number of Subscriptions here. The
+ * fact that we duplicate the subscription and move over the content is just
+ * an implementtion detail.
+ * server->serverDiagnosticsSummary.currentSubscriptionCount++;
+ * server->serverDiagnosticsSummary.cumulatedSubscriptionCount++;
+ *
+ * Update the diagnostics statistics: */
+#ifdef UA_ENABLE_DIAGNOSTICS
+ if(oldSession &&
+ UA_order(&oldSession->clientDescription,
+ &session->clientDescription,
+ &UA_TYPES[UA_TYPES_APPLICATIONDESCRIPTION]) == UA_ORDER_EQ)
+ sub->transferredToSameClientCount++;
+ else
+ sub->transferredToAltClientCount++;
+#endif
+
+ /* Immediately try to publish on the new Subscription. This might put it
+ * into the "late subscription" mode. */
+ UA_Subscription_publish(server, newSub);
+}
+
+void Service_TransferSubscriptions(UA_Server *server, UA_Session *session,
+ const UA_TransferSubscriptionsRequest *request,
+ UA_TransferSubscriptionsResponse *response) {
+ UA_LOG_DEBUG_SESSION(&server->config.logger, session,
+ "Processing TransferSubscriptionsRequest");
+ UA_LOCK_ASSERT(&server->serviceMutex, 1);
+
+ response->responseHeader.serviceResult =
+ UA_Server_processServiceOperations(server, session,
+ (UA_ServiceOperation)Operation_TransferSubscription,
+ &request->sendInitialValues,
+ &request->subscriptionIdsSize, &UA_TYPES[UA_TYPES_UINT32],
+ &response->resultsSize, &UA_TYPES[UA_TYPES_TRANSFERRESULT]);
}
#endif /* UA_ENABLE_SUBSCRIPTIONS */
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/src/server/ua_services_monitoreditem.c" ***********************************/
+/**** amalgamated original file "/src/server/ua_services_monitoreditem.c" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -37703,6 +40954,10 @@ Service_Republish(UA_Server *server, UA_Session *session,
* Copyright 2017 (c) Henrik Norrman
* Copyright 2017-2018 (c) Thomas Stalder, Blue Time Concept SA
* Copyright 2018 (c) Fabian Arndt, Root-Core
+ * Copyright 2020 (c) Kalycito Infotech Private Limited
+ * Copyright 2021 (c) Uranik, Berisha
+ * Copyright 2021 (c) Ammar, Morshed
+ * Copyright 2021 (c) Fraunhofer IOSB (Author: Andreas Ebner)
*/
@@ -37714,7 +40969,7 @@ Service_Republish(UA_Server *server, UA_Session *session,
* UARange property of the variable */
static UA_StatusCode
setAbsoluteFromPercentageDeadband(UA_Server *server, UA_Session *session,
- UA_MonitoredItem *mon, UA_DataChangeFilter *filter) {
+ const UA_MonitoredItem *mon, UA_DataChangeFilter *filter) {
/* A valid deadband? */
if(filter->deadbandValue < 0.0 || filter->deadbandValue > 100.0)
return UA_STATUSCODE_BADDEADBANDFILTERINVALID;
@@ -37722,7 +40977,7 @@ setAbsoluteFromPercentageDeadband(UA_Server *server, UA_Session *session,
/* Browse for the percent range */
UA_QualifiedName qn = UA_QUALIFIEDNAME(0, "EURange");
UA_BrowsePathResult bpr =
- browseSimplifiedBrowsePath(server, mon->monitoredNodeId, 1, &qn);
+ browseSimplifiedBrowsePath(server, mon->itemToMonitor.nodeId, 1, &qn);
if(bpr.statusCode != UA_STATUSCODE_GOOD || bpr.targetsSize < 1) {
UA_BrowsePathResult_clear(&bpr);
return UA_STATUSCODE_BADFILTERNOTALLOWED;
@@ -37743,9 +40998,10 @@ setAbsoluteFromPercentageDeadband(UA_Server *server, UA_Session *session,
}
/* Compute the abs deadband */
- UA_Range* euRange = (UA_Range*)rangeVal.value.data;
- UA_Double absDeadband =
- (filter->deadbandValue/100.0) * (euRange->high - euRange->low);
+ UA_Range *euRange = (UA_Range*)rangeVal.value.data;
+ UA_Double absDeadband = (filter->deadbandValue/100.0) * (euRange->high - euRange->low);
+
+ UA_DataValue_clear(&rangeVal);
/* EURange invalid or NaN? */
if(absDeadband < 0.0 || absDeadband != absDeadband) {
@@ -37753,25 +41009,85 @@ setAbsoluteFromPercentageDeadband(UA_Server *server, UA_Session *session,
return UA_STATUSCODE_BADFILTERNOTALLOWED;
}
- mon->filter.dataChangeFilter.trigger = filter->trigger;
- mon->filter.dataChangeFilter.deadbandType = UA_DEADBANDTYPE_ABSOLUTE;
- mon->filter.dataChangeFilter.deadbandValue = absDeadband;
+ /* Adjust the original filter */
+ filter->deadbandType = UA_DEADBANDTYPE_ABSOLUTE;
+ filter->deadbandValue = absDeadband;
return UA_STATUSCODE_GOOD;
}
#endif /* UA_ENABLE_DA */
-static UA_StatusCode
-setMonitoredItemSettings(UA_Server *server, UA_Session *session, UA_MonitoredItem *mon,
- UA_MonitoringMode monitoringMode,
- const UA_MonitoringParameters *params,
- const UA_DataType* dataType) {
- UA_LOCK_ASSERT(server->serviceMutex, 1);
+void
+Service_SetTriggering(UA_Server *server, UA_Session *session,
+ const UA_SetTriggeringRequest *request,
+ UA_SetTriggeringResponse *response) {
+ /* Nothing to do? */
+ if(request->linksToRemoveSize == 0 &&
+ request->linksToAddSize == 0) {
+ response->responseHeader.serviceResult = UA_STATUSCODE_BADNOTHINGTODO;
+ return;
+ }
- UA_StatusCode retval = UA_STATUSCODE_GOOD;
+ /* Get the Subscription */
+ UA_Subscription *sub = UA_Session_getSubscriptionById(session, request->subscriptionId);
+ if(!sub) {
+ response->responseHeader.serviceResult = UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
+ return;
+ }
+
+ /* Get the MonitoredItem */
+ UA_MonitoredItem *mon = UA_Subscription_getMonitoredItem(sub, request->triggeringItemId);
+ if(!mon) {
+ response->responseHeader.serviceResult = UA_STATUSCODE_BADMONITOREDITEMIDINVALID;
+ return;
+ }
+
+ /* Allocate the results arrays */
+ if(request->linksToRemoveSize > 0) {
+ response->removeResults = (UA_StatusCode*)
+ UA_Array_new(request->linksToRemoveSize, &UA_TYPES[UA_TYPES_STATUSCODE]);
+ if(!response->removeResults) {
+ response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
+ return;
+ }
+ response->removeResultsSize = request->linksToRemoveSize;
+ }
+
+ if(request->linksToAddSize> 0) {
+ response->addResults = (UA_StatusCode*)
+ UA_Array_new(request->linksToAddSize, &UA_TYPES[UA_TYPES_STATUSCODE]);
+ if(!response->addResults) {
+ UA_Array_delete(response->removeResults,
+ request->linksToAddSize, &UA_TYPES[UA_TYPES_STATUSCODE]);
+ response->removeResults = NULL;
+ response->removeResultsSize = 0;
+ response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
+ return;
+ }
+ response->addResultsSize = request->linksToAddSize;
+ }
+
+ /* Apply the changes */
+ for(size_t i = 0; i < request->linksToRemoveSize; i++)
+ response->removeResults[i] =
+ UA_MonitoredItem_removeLink(sub, mon, request->linksToRemove[i]);
- if(mon->attributeId == UA_ATTRIBUTEID_EVENTNOTIFIER) {
- /* Event MonitoredItem */
+ for(size_t i = 0; i < request->linksToAddSize; i++)
+ response->addResults[i] =
+ UA_MonitoredItem_addLink(sub, mon, request->linksToAdd[i]);
+}
+
+/* Verify and adjust the parameters of a MonitoredItem */
+static UA_StatusCode
+checkAdjustMonitoredItemParams(UA_Server *server, UA_Session *session,
+ const UA_MonitoredItem *mon,
+ const UA_DataType* valueType,
+ UA_MonitoringParameters *params) {
+ UA_LOCK_ASSERT(&server->serviceMutex, 1);
+
+ /* Check the filter */
+ if(mon->itemToMonitor.attributeId == UA_ATTRIBUTEID_EVENTNOTIFIER) {
+ /* Event MonitoredItems need a filter */
#ifndef UA_ENABLE_SUBSCRIPTIONS_EVENTS
return UA_STATUSCODE_BADNOTSUPPORTED;
#else
@@ -37780,110 +41096,158 @@ setMonitoredItemSettings(UA_Server *server, UA_Session *session, UA_MonitoredIte
return UA_STATUSCODE_BADEVENTFILTERINVALID;
if(params->filter.content.decoded.type != &UA_TYPES[UA_TYPES_EVENTFILTER])
return UA_STATUSCODE_BADEVENTFILTERINVALID;
- UA_EventFilter_clear(&mon->filter.eventFilter);
- retval = UA_EventFilter_copy((UA_EventFilter *)params->filter.content.decoded.data,
- &mon->filter.eventFilter);
#endif
} else {
- /* DataChange MonitoredItem */
+ /* DataChange MonitoredItem. Can be "no filter" which defaults to
+ * triggering on Status and Value. */
if(params->filter.encoding != UA_EXTENSIONOBJECT_DECODED &&
- params->filter.encoding != UA_EXTENSIONOBJECT_DECODED_NODELETE) {
- /* Default: Look for status and value */
- UA_DataChangeFilter_clear(&mon->filter.dataChangeFilter);
- mon->filter.dataChangeFilter.trigger = UA_DATACHANGETRIGGER_STATUSVALUE;
- } else if(params->filter.content.decoded.type == &UA_TYPES[UA_TYPES_DATACHANGEFILTER]) {
- UA_DataChangeFilter *filter = (UA_DataChangeFilter *)params->filter.content.decoded.data;
+ params->filter.encoding != UA_EXTENSIONOBJECT_DECODED_NODELETE &&
+ params->filter.encoding != UA_EXTENSIONOBJECT_ENCODED_NOBODY)
+ return UA_STATUSCODE_BADMONITOREDITEMFILTERUNSUPPORTED;
+
+ /* If the filter ExtensionObject has a body, then it must be a
+ * DataChangeFilter */
+ if(params->filter.encoding != UA_EXTENSIONOBJECT_ENCODED_NOBODY &&
+ params->filter.content.decoded.type != &UA_TYPES[UA_TYPES_DATACHANGEFILTER])
+ return UA_STATUSCODE_BADFILTERNOTALLOWED;
+
+ /* Check the deadband and adjust if necessary. */
+ if(params->filter.content.decoded.type == &UA_TYPES[UA_TYPES_DATACHANGEFILTER]) {
+ UA_DataChangeFilter *filter = (UA_DataChangeFilter *)
+ params->filter.content.decoded.data;
switch(filter->deadbandType) {
case UA_DEADBANDTYPE_NONE:
- mon->filter.dataChangeFilter = *filter;
break;
case UA_DEADBANDTYPE_ABSOLUTE:
- if(!dataType || !UA_DataType_isNumeric(dataType))
+ if(mon->itemToMonitor.attributeId != UA_ATTRIBUTEID_VALUE ||
+ !valueType || !UA_DataType_isNumeric(valueType))
return UA_STATUSCODE_BADFILTERNOTALLOWED;
- mon->filter.dataChangeFilter = *filter;
break;
- case UA_DEADBANDTYPE_PERCENT:
#ifdef UA_ENABLE_DA
- if(!dataType || !UA_DataType_isNumeric(dataType))
+ case UA_DEADBANDTYPE_PERCENT: {
+ if(mon->itemToMonitor.attributeId != UA_ATTRIBUTEID_VALUE ||
+ !valueType || !UA_DataType_isNumeric(valueType))
return UA_STATUSCODE_BADFILTERNOTALLOWED;
- retval = setAbsoluteFromPercentageDeadband(server, session, mon, filter);
+ /* If percentage deadband is supported, look up the range values
+ * and precompute as if it was an absolute deadband. */
+ UA_StatusCode res =
+ setAbsoluteFromPercentageDeadband(server, session, mon, filter);
+ if(res != UA_STATUSCODE_GOOD)
+ return res;
break;
-#else
- return UA_STATUSCODE_BADMONITOREDITEMFILTERUNSUPPORTED;
+ }
#endif
default:
return UA_STATUSCODE_BADMONITOREDITEMFILTERUNSUPPORTED;
}
- } else {
- return UA_STATUSCODE_BADMONITOREDITEMFILTERUNSUPPORTED;
}
}
- if(retval != UA_STATUSCODE_GOOD)
- return retval;
-
- /* <-- The point of no return --> */
-
- /* Unregister the callback */
- UA_MonitoredItem_unregisterSampleCallback(server, mon);
-
- /* Remove the old samples */
- UA_ByteString_clear(&mon->lastSampledValue);
- UA_Variant_clear(&mon->lastValue);
-
- /* ClientHandle */
- mon->clientHandle = params->clientHandle;
-
- /* SamplingInterval */
- UA_Double samplingInterval = params->samplingInterval;
+ /* Read the minimum sampling interval for the variable. The sampling
+ * interval of the MonitoredItem must not be less than that. */
+ if(mon->itemToMonitor.attributeId == UA_ATTRIBUTEID_VALUE) {
+ const UA_Node *node = UA_NODESTORE_GET(server, &mon->itemToMonitor.nodeId);
+ if(node) {
+ const UA_VariableNode *vn = &node->variableNode;
+ if(node->head.nodeClass == UA_NODECLASS_VARIABLE &&
+ params->samplingInterval < vn->minimumSamplingInterval)
+ params->samplingInterval = vn->minimumSamplingInterval;
+ UA_NODESTORE_RELEASE(server, node);
+ }
+ }
+
+ /* Adjust to sampling interval to lie within the limits */
+ if(params->samplingInterval <= 0.0) {
+ /* A sampling interval of zero is possible and indicates that the
+ * MonitoredItem is checked for every write operation */
+ params->samplingInterval = 0.0;
+ } else {
+ UA_BOUNDEDVALUE_SETWBOUNDS(server->config.samplingIntervalLimits,
+ params->samplingInterval, params->samplingInterval);
+ /* Check for NaN */
+ if(mon->parameters.samplingInterval != mon->parameters.samplingInterval)
+ params->samplingInterval = server->config.samplingIntervalLimits.min;
+ }
- if(mon->attributeId == UA_ATTRIBUTEID_VALUE) {
- const UA_VariableNode *vn = (const UA_VariableNode *)
- UA_NODESTORE_GET(server, &mon->monitoredNodeId);
- if(vn) {
- if(vn->nodeClass == UA_NODECLASS_VARIABLE &&
- samplingInterval < vn->minimumSamplingInterval)
- samplingInterval = vn->minimumSamplingInterval;
- UA_NODESTORE_RELEASE(server, (const UA_Node *)vn);
+ /* Adjust the maximum queue size */
+#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
+ if(mon->itemToMonitor.attributeId == UA_ATTRIBUTEID_EVENTNOTIFIER) {
+ /* 0 => Set to the configured maximum. Otherwise adjust with configured limits */
+ if(params->queueSize == 0) {
+ params->queueSize = server->config.queueSizeLimits.max;
+ } else {
+ UA_BOUNDEDVALUE_SETWBOUNDS(server->config.queueSizeLimits,
+ params->queueSize, params->queueSize);
}
+ } else
+#endif
+ {
+ /* 0 or 1 => queue-size 1. Otherwise adjust with configured limits */
+ if(params->queueSize == 0)
+ params->queueSize = 1;
+ if(params->queueSize != 1)
+ UA_BOUNDEDVALUE_SETWBOUNDS(server->config.queueSizeLimits,
+ params->queueSize, params->queueSize);
}
- UA_BOUNDEDVALUE_SETWBOUNDS(server->config.samplingIntervalLimits,
- samplingInterval, mon->samplingInterval);
- if(samplingInterval != samplingInterval) /* Check for nan */
- mon->samplingInterval = server->config.samplingIntervalLimits.min;
+ return UA_STATUSCODE_GOOD;
+}
- /* QueueSize */
- UA_BOUNDEDVALUE_SETWBOUNDS(server->config.queueSizeLimits,
- params->queueSize, mon->maxQueueSize);
+#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
+static UA_StatusCode
+checkEventFilterParam(UA_Server *server, UA_Session *session,
+ const UA_MonitoredItem *mon,
+ UA_MonitoringParameters *params){
+ if(mon->itemToMonitor.attributeId != UA_ATTRIBUTEID_EVENTNOTIFIER)
+ return UA_STATUSCODE_GOOD;
- /* DiscardOldest */
- mon->discardOldest = params->discardOldest;
+ UA_EventFilter *eventFilter =
+ (UA_EventFilter *) params->filter.content.decoded.data;
- /* Register sample callback if reporting is enabled */
- mon->monitoringMode = monitoringMode;
- if(monitoringMode == UA_MONITORINGMODE_SAMPLING ||
- monitoringMode == UA_MONITORINGMODE_REPORTING)
- return UA_MonitoredItem_registerSampleCallback(server, mon);
+ if(eventFilter == NULL)
+ return UA_STATUSCODE_BADEVENTFILTERINVALID;
- return UA_STATUSCODE_GOOD;
-}
+ //TODO make the maximum select clause size param an server-config parameter
+ if(eventFilter->selectClausesSize > 128)
+ return UA_STATUSCODE_BADCONFIGURATIONERROR;
-static const UA_String binaryEncoding = {sizeof("Default Binary") - 1, (UA_Byte *)"Default Binary"};
+ //check the where clause for logical consistency
+ if(eventFilter->whereClause.elementsSize != 0) {
+ UA_ContentFilterResult contentFilterResult;
+ UA_Event_staticWhereClauseValidation(server, &eventFilter->whereClause,
+ &contentFilterResult);
+ for(size_t i = 0; i < contentFilterResult.elementResultsSize; ++i) {
+ if(contentFilterResult.elementResults[i].statusCode != UA_STATUSCODE_GOOD){
+ //ToDo currently we return the first non good status code, check if
+ //we can use the detailed contentFilterResult later
+ UA_StatusCode whereResult =
+ contentFilterResult.elementResults[i].statusCode;
+ UA_ContentFilterResult_clear(&contentFilterResult);
+ return whereResult;
+ }
+ }
+ UA_ContentFilterResult_clear(&contentFilterResult);
+ }
+ //check the select clause for logical consistency
+ UA_StatusCode selectClauseValidationResult[128];
+ UA_Event_staticSelectClauseValidation(server,eventFilter,
+ selectClauseValidationResult);
+ for(size_t i = 0; i < eventFilter->selectClausesSize; ++i){
+ //ToDo currently we return the first non good status code, check if
+ //we can use the detailed status code list later
+ if(selectClauseValidationResult[i] != UA_STATUSCODE_GOOD){
+ return selectClauseValidationResult[i];
+ }
+ }
-#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
-static UA_StatusCode
-UA_Server_addMonitoredItemToNodeEditNodeCallback(UA_Server *server, UA_Session *session,
- UA_Node *node, void *data) {
- /* data is the MonitoredItem */
- /* SLIST_INSERT_HEAD */
- ((UA_MonitoredItem *)data)->next = ((UA_ObjectNode *)node)->monitoredItemQueue;
- ((UA_ObjectNode *)node)->monitoredItemQueue = (UA_MonitoredItem *)data;
return UA_STATUSCODE_GOOD;
}
#endif
-/* Thread-local variables to pass additional arguments into the operation */
+static const UA_String
+binaryEncoding = {sizeof("Default Binary") - 1, (UA_Byte *)"Default Binary"};
+
+/* Structure to pass additional arguments into the operation */
struct createMonContext {
UA_Subscription *sub;
UA_TimestampsToReturn timestampsToReturn;
@@ -37894,44 +41258,27 @@ struct createMonContext {
};
static void
-Operation_CreateMonitoredItem(UA_Server *server, UA_Session *session, struct createMonContext *cmc,
+Operation_CreateMonitoredItem(UA_Server *server, UA_Session *session,
+ struct createMonContext *cmc,
const UA_MonitoredItemCreateRequest *request,
UA_MonitoredItemCreateResult *result) {
- UA_LOCK_ASSERT(server->serviceMutex, 1);
+ UA_LOCK_ASSERT(&server->serviceMutex, 1);
/* Check available capacity */
if(cmc->sub &&
(((server->config.maxMonitoredItems != 0) &&
- (server->numMonitoredItems >= server->config.maxMonitoredItems)) ||
+ (server->monitoredItemsSize >= server->config.maxMonitoredItems)) ||
((server->config.maxMonitoredItemsPerSubscription != 0) &&
(cmc->sub->monitoredItemsSize >= server->config.maxMonitoredItemsPerSubscription)))) {
result->statusCode = UA_STATUSCODE_BADTOOMANYMONITOREDITEMS;
return;
}
- /* Make an example read to get errors in the itemToMonitor. Allow return
- * codes "good" and "uncertain", as well as a list of statuscodes that might
- * be repaired inside the data source. */
- UA_DataValue v = UA_Server_readWithSession(server, session, &request->itemToMonitor,
- cmc->timestampsToReturn);
- if(v.hasStatus && (v.status >> 30) > 1 &&
- v.status != UA_STATUSCODE_BADRESOURCEUNAVAILABLE &&
- v.status != UA_STATUSCODE_BADCOMMUNICATIONERROR &&
- v.status != UA_STATUSCODE_BADWAITINGFORINITIALDATA &&
- v.status != UA_STATUSCODE_BADUSERACCESSDENIED &&
- v.status != UA_STATUSCODE_BADNOTREADABLE &&
- v.status != UA_STATUSCODE_BADINDEXRANGENODATA) {
- result->statusCode = v.status;
- UA_DataValue_clear(&v);
- return;
- }
-
/* Check if the encoding is supported */
if(request->itemToMonitor.dataEncoding.name.length > 0 &&
(!UA_String_equal(&binaryEncoding, &request->itemToMonitor.dataEncoding.name) ||
request->itemToMonitor.dataEncoding.namespaceIndex != 0)) {
result->statusCode = UA_STATUSCODE_BADDATAENCODINGUNSUPPORTED;
- UA_DataValue_clear(&v);
return;
}
@@ -37939,97 +41286,153 @@ Operation_CreateMonitoredItem(UA_Server *server, UA_Session *session, struct cre
if(request->itemToMonitor.attributeId != UA_ATTRIBUTEID_VALUE &&
request->itemToMonitor.dataEncoding.name.length > 0) {
result->statusCode = UA_STATUSCODE_BADDATAENCODINGINVALID;
+ return;
+ }
+
+ /* Make an example read to check the itemToMonitor. The DataSource itself
+ * could return a (temporary) error. This should still result in a valid
+ * MonitoredItem. Only a few StatusCodes are considered unrecoverable and
+ * lead to an abort:
+ * - The Node does not exist
+ * - The AttributeId does not match the NodeClass
+ * - The Session does not have sufficient access rights
+ * - The indicated encoding is not supported or not valid */
+ UA_DataValue v = UA_Server_readWithSession(server, session, &request->itemToMonitor,
+ cmc->timestampsToReturn);
+ if(v.hasStatus &&
+ (v.status == UA_STATUSCODE_BADNODEIDUNKNOWN ||
+ v.status == UA_STATUSCODE_BADATTRIBUTEIDINVALID ||
+ v.status == UA_STATUSCODE_BADDATAENCODINGUNSUPPORTED ||
+ v.status == UA_STATUSCODE_BADDATAENCODINGINVALID ||
+ v.status == UA_STATUSCODE_BADINDEXRANGEINVALID
+ /* Part 4, 5.12.2 CreateMonitoredItems: When a user adds a monitored
+ * item that the user is denied read access to, the add operation for
+ * the item shall succeed and the bad status Bad_NotReadable or
+ * Bad_UserAccessDenied shall be returned in the Publish response.
+ * v.status == UA_STATUSCODE_BADNOTREADABLE
+ * v.status == UA_STATUSCODE_BADUSERACCESSDENIED
+ *
+ * The IndexRange error can change depending on the value.
+ * v.status == UA_STATUSCODE_BADINDEXRANGENODATA */
+ )) {
+ result->statusCode = v.status;
UA_DataValue_clear(&v);
return;
}
+ /* Adding an Event MonitoredItem */
+#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
+ if(request->itemToMonitor.attributeId == UA_ATTRIBUTEID_EVENTNOTIFIER) {
+ /* TODO: Only remote clients can add Event-MonitoredItems at the moment */
+ if(!cmc->sub) {
+ UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Only remote clients can add Event-MonitoredItems");
+ result->statusCode = UA_STATUSCODE_BADNOTSUPPORTED;
+ UA_DataValue_clear(&v);
+ return;
+ }
+
+ /* If the 'SubscribeToEvents' bit of EventNotifier attribute is
+ * zero, then the object cannot be subscribed to monitor events */
+ if(!v.hasValue || !v.value.data) {
+ result->statusCode = UA_STATUSCODE_BADINTERNALERROR;
+ UA_DataValue_clear(&v);
+ return;
+ }
+ UA_Byte eventNotifierValue = *((UA_Byte *)v.value.data);
+ if((eventNotifierValue & 0x01) != 1) {
+ result->statusCode = UA_STATUSCODE_BADNOTSUPPORTED;
+ UA_LOG_INFO_SUBSCRIPTION(&server->config.logger, cmc->sub,
+ "Could not create a MonitoredItem as the "
+ "'SubscribeToEvents' bit of the EventNotifier "
+ "attribute is not set");
+ UA_DataValue_clear(&v);
+ return;
+ }
+ }
+#endif
+
+ const UA_DataType *valueType = v.value.type;
+ UA_DataValue_clear(&v);
+
/* Allocate the MonitoredItem */
- size_t nmsize = sizeof(UA_MonitoredItem);
- if(!cmc->sub)
- nmsize = sizeof(UA_LocalMonitoredItem);
- UA_MonitoredItem *newMon = (UA_MonitoredItem*)UA_malloc(nmsize);
+ UA_MonitoredItem *newMon = NULL;
+ if(cmc->sub) {
+ newMon = (UA_MonitoredItem*)UA_malloc(sizeof(UA_MonitoredItem));
+ } else {
+ UA_LocalMonitoredItem *localMon = (UA_LocalMonitoredItem*)
+ UA_malloc(sizeof(UA_LocalMonitoredItem));
+ if(localMon) {
+ /* Set special values only for the LocalMonitoredItem */
+ localMon->context = cmc->context;
+ localMon->callback.dataChangeCallback = cmc->dataChangeCallback;
+ }
+ newMon = &localMon->monitoredItem;
+ }
if(!newMon) {
result->statusCode = UA_STATUSCODE_BADOUTOFMEMORY;
- UA_DataValue_clear(&v);
return;
}
/* Initialize the MonitoredItem */
- UA_MonitoredItem_init(newMon, cmc->sub);
- newMon->attributeId = request->itemToMonitor.attributeId;
+ UA_MonitoredItem_init(newMon);
+ newMon->subscription = cmc->sub; /* Can be NULL for local MonitoredItems */
newMon->timestampsToReturn = cmc->timestampsToReturn;
- UA_StatusCode retval = UA_STATUSCODE_GOOD;
- retval |= UA_NodeId_copy(&request->itemToMonitor.nodeId, &newMon->monitoredNodeId);
- retval |= UA_String_copy(&request->itemToMonitor.indexRange, &newMon->indexRange);
- retval |= setMonitoredItemSettings(server, session, newMon, request->monitoringMode,
- &request->requestedParameters, v.value.type);
- UA_DataValue_clear(&v);
- if(retval != UA_STATUSCODE_GOOD) {
- UA_LOG_INFO_SESSION(&server->config.logger, session,
- "Subscription %" PRIu32 " | Could not create a MonitoredItem "
- "with StatusCode %s", cmc->sub ? cmc->sub->subscriptionId : 0,
- UA_StatusCode_name(retval));
- result->statusCode = retval;
- UA_MonitoredItem_delete(server, newMon);
- return;
- }
-
- /* Add to the subscriptions or the local MonitoredItems */
- if(cmc->sub) {
- newMon->monitoredItemId = ++cmc->sub->lastMonitoredItemId;
- UA_Subscription_addMonitoredItem(server, cmc->sub, newMon);
+ result->statusCode |= UA_ReadValueId_copy(&request->itemToMonitor,
+ &newMon->itemToMonitor);
+ result->statusCode |= UA_MonitoringParameters_copy(&request->requestedParameters,
+ &newMon->parameters);
+ result->statusCode |= checkAdjustMonitoredItemParams(server, session, newMon,
+ valueType, &newMon->parameters);
#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
- if(newMon->attributeId == UA_ATTRIBUTEID_EVENTNOTIFIER) {
- /* Insert the monitored item into the node's queue */
- UA_Server_editNode(server, NULL, &newMon->monitoredNodeId,
- UA_Server_addMonitoredItemToNodeEditNodeCallback, newMon);
- }
+ result->statusCode |= checkEventFilterParam(server, session, newMon,
+ &newMon->parameters);
#endif
- } else {
- //TODO support events for local monitored items
- UA_LocalMonitoredItem *localMon = (UA_LocalMonitoredItem*)newMon;
- localMon->context = cmc->context;
- localMon->callback.dataChangeCallback = cmc->dataChangeCallback;
- newMon->monitoredItemId = ++server->lastLocalMonitoredItemId;
- LIST_INSERT_HEAD(&server->localMonitoredItems, newMon, listEntry);
+ if(result->statusCode != UA_STATUSCODE_GOOD) {
+ UA_LOG_INFO_SUBSCRIPTION(&server->config.logger, cmc->sub,
+ "Could not create a MonitoredItem "
+ "with StatusCode %s",
+ UA_StatusCode_name(result->statusCode));
+ UA_MonitoredItem_delete(server, newMon);
+ return;
}
- /* Register MonitoredItem in userland */
- if(server->config.monitoredItemRegisterCallback) {
- void *targetContext = NULL;
- getNodeContext(server, request->itemToMonitor.nodeId, &targetContext);
- UA_UNLOCK(server->serviceMutex);
- server->config.monitoredItemRegisterCallback(server, &session->sessionId,
- session->sessionHandle,
- &request->itemToMonitor.nodeId,
- targetContext, newMon->attributeId, false);
- UA_LOCK(server->serviceMutex);
- newMon->registered = true;
- }
+ /* Initialize the value status so the first sample always passes the filter */
+ newMon->lastValue.hasStatus = true;
+ newMon->lastValue.status = ~(UA_StatusCode)0;
- UA_LOG_INFO_SESSION(&server->config.logger, session,
- "Subscription %" PRIu32 " | MonitoredItem %" PRIi32 " | "
- "Created the MonitoredItem",
- cmc->sub ? cmc->sub->subscriptionId : 0,
- newMon->monitoredItemId);
+ /* Register the Monitoreditem in the server and subscription */
+ UA_Server_registerMonitoredItem(server, newMon);
- /* Create the first sample */
- if(request->monitoringMode == UA_MONITORINGMODE_REPORTING &&
- newMon->attributeId != UA_ATTRIBUTEID_EVENTNOTIFIER)
- monitoredItem_sampleCallback(server, newMon);
+ /* Activate the MonitoredItem */
+ result->statusCode |=
+ UA_MonitoredItem_setMonitoringMode(server, newMon, request->monitoringMode);
+ if(result->statusCode != UA_STATUSCODE_GOOD) {
+ UA_MonitoredItem_delete(server, newMon);
+ return;
+ }
/* Prepare the response */
- result->revisedSamplingInterval = newMon->samplingInterval;
- result->revisedQueueSize = newMon->maxQueueSize;
+ result->revisedSamplingInterval = newMon->parameters.samplingInterval;
+ result->revisedQueueSize = newMon->parameters.queueSize;
result->monitoredItemId = newMon->monitoredItemId;
+
+ UA_LOG_INFO_SUBSCRIPTION(&server->config.logger, cmc->sub,
+ "MonitoredItem %" PRIi32 " | "
+ "Created the MonitoredItem "
+ "(Sampling Interval: %.2fms, Queue Size: %lu)",
+ newMon->monitoredItemId,
+ newMon->parameters.samplingInterval,
+ (unsigned long)newMon->parameters.queueSize);
}
void
Service_CreateMonitoredItems(UA_Server *server, UA_Session *session,
const UA_CreateMonitoredItemsRequest *request,
UA_CreateMonitoredItemsResponse *response) {
- UA_LOG_DEBUG_SESSION(&server->config.logger, session, "Processing CreateMonitoredItemsRequest");
- UA_LOCK_ASSERT(server->serviceMutex, 1);
+ UA_LOG_DEBUG_SESSION(&server->config.logger, session,
+ "Processing CreateMonitoredItemsRequest");
+ UA_LOCK_ASSERT(&server->serviceMutex, 1);
if(server->config.maxMonitoredItemsPerCall != 0 &&
request->itemsToCreateSize > server->config.maxMonitoredItemsPerCall) {
@@ -38056,9 +41459,12 @@ Service_CreateMonitoredItems(UA_Server *server, UA_Session *session,
cmc.sub->currentLifetimeCount = 0;
response->responseHeader.serviceResult =
- UA_Server_processServiceOperations(server, session, (UA_ServiceOperation)Operation_CreateMonitoredItem, &cmc,
- &request->itemsToCreateSize, &UA_TYPES[UA_TYPES_MONITOREDITEMCREATEREQUEST],
- &response->resultsSize, &UA_TYPES[UA_TYPES_MONITOREDITEMCREATERESULT]);
+ UA_Server_processServiceOperations(server, session,
+ (UA_ServiceOperation)Operation_CreateMonitoredItem,
+ &cmc, &request->itemsToCreateSize,
+ &UA_TYPES[UA_TYPES_MONITOREDITEMCREATEREQUEST],
+ &response->resultsSize,
+ &UA_TYPES[UA_TYPES_MONITOREDITEMCREATERESULT]);
}
UA_MonitoredItemCreateResult
@@ -38075,9 +41481,9 @@ UA_Server_createDataChangeMonitoredItem(UA_Server *server,
UA_MonitoredItemCreateResult result;
UA_MonitoredItemCreateResult_init(&result);
- UA_LOCK(server->serviceMutex);
+ UA_LOCK(&server->serviceMutex);
Operation_CreateMonitoredItem(server, &server->adminSession, &cmc, &item, &result);
- UA_UNLOCK(server->serviceMutex);
+ UA_UNLOCK(&server->serviceMutex);
return result;
}
@@ -38092,36 +41498,69 @@ Operation_ModifyMonitoredItem(UA_Server *server, UA_Session *session, UA_Subscri
return;
}
+ /* Make local copy of the settings */
+ UA_MonitoringParameters params;
+ result->statusCode =
+ UA_MonitoringParameters_copy(&request->requestedParameters, &params);
+ if(result->statusCode != UA_STATUSCODE_GOOD)
+ return;
+
/* Read the current value to test if filters are possible.
* Can return an empty value (v.value.type == NULL). */
- UA_ReadValueId rvid;
- UA_ReadValueId_init(&rvid);
- rvid.nodeId = mon->monitoredNodeId;
- rvid.attributeId = mon->attributeId;
- rvid.indexRange = mon->indexRange;
- UA_DataValue v = UA_Server_readWithSession(server, session, &rvid, mon->timestampsToReturn);
- UA_StatusCode retval = setMonitoredItemSettings(server, session, mon, mon->monitoringMode,
- &request->requestedParameters,
- v.value.type);
+ UA_DataValue v =
+ UA_Server_readWithSession(server, session, &mon->itemToMonitor,
+ mon->timestampsToReturn);
+
+ /* Verify and adjust the new parameters. This still leaves the original
+ * MonitoredItem untouched. */
+ result->statusCode =
+ checkAdjustMonitoredItemParams(server, session, mon,
+ v.value.type, &params);
UA_DataValue_clear(&v);
- if(retval != UA_STATUSCODE_GOOD) {
- result->statusCode = retval;
+ if(result->statusCode != UA_STATUSCODE_GOOD) {
+ UA_MonitoringParameters_clear(&params);
return;
}
- result->revisedSamplingInterval = mon->samplingInterval;
- result->revisedQueueSize = mon->maxQueueSize;
+ /* Store the old sampling interval */
+ UA_Double oldSamplingInterval = mon->parameters.samplingInterval;
+
+ /* Move over the new settings */
+ UA_MonitoringParameters_clear(&mon->parameters);
+ mon->parameters = params;
+
+ /* Re-register the callback if necessary */
+ if(oldSamplingInterval != mon->parameters.samplingInterval) {
+ UA_MonitoredItem_unregisterSampling(server, mon);
+ result->statusCode =
+ UA_MonitoredItem_setMonitoringMode(server, mon, mon->monitoringMode);
+ }
+
+ result->revisedSamplingInterval = mon->parameters.samplingInterval;
+ result->revisedQueueSize = mon->parameters.queueSize;
/* Remove some notifications if the queue is now too small */
UA_MonitoredItem_ensureQueueSpace(server, mon);
+
+ /* Remove the overflow bits if the queue has now a size of 1 */
+ UA_MonitoredItem_removeOverflowInfoBits(mon);
+
+ UA_LOG_INFO_SUBSCRIPTION(&server->config.logger, sub,
+ "MonitoredItem %" PRIi32 " | "
+ "Modified the MonitoredItem "
+ "(Sampling Interval: %fms, Queue Size: %lu)",
+ mon->monitoredItemId,
+ mon->parameters.samplingInterval,
+ (unsigned long)mon->queueSize);
}
void
Service_ModifyMonitoredItems(UA_Server *server, UA_Session *session,
const UA_ModifyMonitoredItemsRequest *request,
UA_ModifyMonitoredItemsResponse *response) {
- UA_LOG_DEBUG_SESSION(&server->config.logger, session, "Processing ModifyMonitoredItemsRequest");
- UA_LOCK_ASSERT(server->serviceMutex, 1);
+ UA_LOG_DEBUG_SESSION(&server->config.logger, session,
+ "Processing ModifyMonitoredItemsRequest");
+ UA_LOCK_ASSERT(&server->serviceMutex, 1);
if(server->config.maxMonitoredItemsPerCall != 0 &&
request->itemsToModifySize > server->config.maxMonitoredItemsPerCall) {
@@ -38146,9 +41585,11 @@ Service_ModifyMonitoredItems(UA_Server *server, UA_Session *session,
response->responseHeader.serviceResult =
UA_Server_processServiceOperations(server, session,
- (UA_ServiceOperation)Operation_ModifyMonitoredItem, sub,
- &request->itemsToModifySize, &UA_TYPES[UA_TYPES_MONITOREDITEMMODIFYREQUEST],
- &response->resultsSize, &UA_TYPES[UA_TYPES_MONITOREDITEMMODIFYRESULT]);
+ (UA_ServiceOperation)Operation_ModifyMonitoredItem,
+ sub, &request->itemsToModifySize,
+ &UA_TYPES[UA_TYPES_MONITOREDITEMMODIFYREQUEST],
+ &response->resultsSize,
+ &UA_TYPES[UA_TYPES_MONITOREDITEMMODIFYRESULT]);
}
struct setMonitoringContext {
@@ -38165,72 +41606,7 @@ Operation_SetMonitoringMode(UA_Server *server, UA_Session *session,
*result = UA_STATUSCODE_BADMONITOREDITEMIDINVALID;
return;
}
- UA_Subscription *sub = mon->subscription;
-
- /* Check if the MonitoringMode is valid or not */
- if(smc->monitoringMode > UA_MONITORINGMODE_REPORTING) {
- *result = UA_STATUSCODE_BADMONITORINGMODEINVALID;
- return;
- }
-
- /* Nothing has changed */
- if(mon->monitoringMode == smc->monitoringMode)
- return;
-
- mon->monitoringMode = smc->monitoringMode;
-
- /* When reporting is enabled, put all notifications that were already
- * sampled into the global queue of the subscription. When sampling is
- * enabled, remove all notifications from the global queue. !!! This needs
- * to be the same operation as in UA_Notification_enqueue !!! */
- if(mon->monitoringMode == UA_MONITORINGMODE_REPORTING) {
- UA_Notification *notification;
- TAILQ_FOREACH(notification, &mon->queue, listEntry) {
- TAILQ_INSERT_TAIL(&sub->notificationQueue, notification, globalEntry);
- ++sub->notificationQueueSize;
-#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
- if(mon->attributeId == UA_ATTRIBUTEID_EVENTNOTIFIER) {
- ++sub->eventNotifications;
- } else
-#endif
- {
- ++sub->dataChangeNotifications;
- }
- }
- /* Register the sampling callback with an interval */
- *result = UA_MonitoredItem_registerSampleCallback(server, mon);
- } else if(mon->monitoringMode == UA_MONITORINGMODE_SAMPLING) {
- UA_Notification *notification;
- TAILQ_FOREACH(notification, &mon->queue, listEntry) {
- TAILQ_REMOVE(&sub->notificationQueue, notification, globalEntry);
- TAILQ_NEXT(notification, globalEntry) = UA_SUBSCRIPTION_QUEUE_SENTINEL;
- --sub->notificationQueueSize;
-#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
- if(mon->attributeId == UA_ATTRIBUTEID_EVENTNOTIFIER) {
- --sub->eventNotifications;
- } else
-#endif
- {
- --sub->dataChangeNotifications;
- }
- }
- /* Register the sampling callback with an interval */
- *result = UA_MonitoredItem_registerSampleCallback(server, mon);
- } else {
- /* UA_MONITORINGMODE_DISABLED */
- UA_MonitoredItem_unregisterSampleCallback(server, mon);
-
- /* Setting the mode to DISABLED or SAMPLING causes all queued Notifications to be deleted */
- UA_Notification *notification, *notification_tmp;
- TAILQ_FOREACH_SAFE(notification, &mon->queue, listEntry, notification_tmp) {
- UA_Notification_dequeue(server, notification);
- UA_Notification_delete(notification);
- }
-
- /* Initialize lastSampledValue */
- UA_ByteString_clear(&mon->lastSampledValue);
- UA_Variant_clear(&mon->lastValue);
- }
+ *result = UA_MonitoredItem_setMonitoringMode(server, mon, smc->monitoringMode);
}
void
@@ -38238,7 +41614,7 @@ Service_SetMonitoringMode(UA_Server *server, UA_Session *session,
const UA_SetMonitoringModeRequest *request,
UA_SetMonitoringModeResponse *response) {
UA_LOG_DEBUG_SESSION(&server->config.logger, session, "Processing SetMonitoringMode");
- UA_LOCK_ASSERT(server->serviceMutex, 1);
+ UA_LOCK_ASSERT(&server->serviceMutex, 1);
if(server->config.maxMonitoredItemsPerCall != 0 &&
request->monitoredItemIdsSize > server->config.maxMonitoredItemsPerCall) {
@@ -38259,15 +41635,23 @@ Service_SetMonitoringMode(UA_Server *server, UA_Session *session,
smc.monitoringMode = request->monitoringMode;
response->responseHeader.serviceResult =
UA_Server_processServiceOperations(server, session,
- (UA_ServiceOperation)Operation_SetMonitoringMode, &smc,
- &request->monitoredItemIdsSize, &UA_TYPES[UA_TYPES_UINT32],
- &response->resultsSize, &UA_TYPES[UA_TYPES_STATUSCODE]);
+ (UA_ServiceOperation)Operation_SetMonitoringMode,
+ &smc, &request->monitoredItemIdsSize,
+ &UA_TYPES[UA_TYPES_UINT32],
+ &response->resultsSize,
+ &UA_TYPES[UA_TYPES_STATUSCODE]);
}
static void
Operation_DeleteMonitoredItem(UA_Server *server, UA_Session *session, UA_Subscription *sub,
const UA_UInt32 *monitoredItemId, UA_StatusCode *result) {
- *result = UA_Subscription_deleteMonitoredItem(server, sub, *monitoredItemId);
+ UA_LOCK_ASSERT(&server->serviceMutex, 1);
+ UA_MonitoredItem *mon = UA_Subscription_getMonitoredItem(sub, *monitoredItemId);
+ if(!mon) {
+ *result = UA_STATUSCODE_BADMONITOREDITEMIDINVALID;
+ return;
+ }
+ UA_MonitoredItem_delete(server, mon);
}
void
@@ -38276,7 +41660,7 @@ Service_DeleteMonitoredItems(UA_Server *server, UA_Session *session,
UA_DeleteMonitoredItemsResponse *response) {
UA_LOG_DEBUG_SESSION(&server->config.logger, session,
"Processing DeleteMonitoredItemsRequest");
- UA_LOCK_ASSERT(server->serviceMutex, 1);
+ UA_LOCK_ASSERT(&server->serviceMutex, 1);
if(server->config.maxMonitoredItemsPerCall != 0 &&
request->monitoredItemIdsSize > server->config.maxMonitoredItemsPerCall) {
@@ -38296,30 +41680,31 @@ Service_DeleteMonitoredItems(UA_Server *server, UA_Session *session,
response->responseHeader.serviceResult =
UA_Server_processServiceOperations(server, session,
- (UA_ServiceOperation)Operation_DeleteMonitoredItem, sub,
- &request->monitoredItemIdsSize, &UA_TYPES[UA_TYPES_UINT32],
- &response->resultsSize, &UA_TYPES[UA_TYPES_STATUSCODE]);
+ (UA_ServiceOperation)Operation_DeleteMonitoredItem,
+ sub, &request->monitoredItemIdsSize,
+ &UA_TYPES[UA_TYPES_UINT32],
+ &response->resultsSize,
+ &UA_TYPES[UA_TYPES_STATUSCODE]);
}
UA_StatusCode
UA_Server_deleteMonitoredItem(UA_Server *server, UA_UInt32 monitoredItemId) {
- UA_LOCK(server->serviceMutex);
- UA_MonitoredItem *mon;
- LIST_FOREACH(mon, &server->localMonitoredItems, listEntry) {
+ UA_LOCK(&server->serviceMutex);
+ UA_MonitoredItem *mon, *mon_tmp;
+ LIST_FOREACH_SAFE(mon, &server->localMonitoredItems, listEntry, mon_tmp) {
if(mon->monitoredItemId != monitoredItemId)
continue;
- LIST_REMOVE(mon, listEntry);
UA_MonitoredItem_delete(server, mon);
- UA_UNLOCK(server->serviceMutex);
+ UA_UNLOCK(&server->serviceMutex);
return UA_STATUSCODE_GOOD;
}
- UA_UNLOCK(server->serviceMutex);
+ UA_UNLOCK(&server->serviceMutex);
return UA_STATUSCODE_BADMONITOREDITEMIDINVALID;
}
#endif /* UA_ENABLE_SUBSCRIPTIONS */
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/src/server/ua_services_securechannel.c" ***********************************/
+/**** amalgamated original file "/src/server/ua_services_securechannel.c" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -38364,7 +41749,7 @@ removeSecureChannel(UA_Server *server, channel_entry *entry,
TAILQ_REMOVE(&server->channels, entry, pointers);
/* Update the statistics */
- UA_SecureChannelStatistics *scs = &server->serverStats.scs;
+ UA_SecureChannelStatistics *scs = &server->secureChannelStatistics;
UA_atomic_subSize(&scs->currentChannelCount, 1);
switch(event) {
case UA_DIAGNOSTICEVENT_CLOSE:
@@ -38392,7 +41777,9 @@ removeSecureChannel(UA_Server *server, channel_entry *entry,
entry->cleanupCallback.callback = (UA_ApplicationCallback)removeSecureChannelCallback;
entry->cleanupCallback.application = NULL;
entry->cleanupCallback.data = entry;
- UA_WorkQueue_enqueueDelayed(&server->workQueue, &entry->cleanupCallback);
+ entry->cleanupCallback.nextTime = UA_DateTime_nowMonotonic() + 1;
+ entry->cleanupCallback.interval = 0; /* Remove the structure */
+ UA_Timer_addTimerEntry(&server->timer, &entry->cleanupCallback, NULL);
}
void
@@ -38415,6 +41802,12 @@ UA_Server_cleanupTimedOutSecureChannels(UA_Server *server,
continue;
}
+ /* Is the SecurityToken already created? */
+ if(entry->channel.securityToken.createdAt == 0) {
+ /* No -> channel is still in progress of being opened, do not remove */
+ continue;
+ }
+
/* Has the SecurityToken timed out? */
UA_DateTime timeout =
entry->channel.securityToken.createdAt +
@@ -38473,13 +41866,11 @@ UA_Server_createSecureChannel(UA_Server *server, UA_Connection *connection) {
/* Check if there exists a free SC, otherwise try to purge one SC without a
* session the purge has been introduced to pass CTT, it is not clear what
* strategy is expected here */
- if(server->serverStats.scs.currentChannelCount >= server->config.maxSecureChannels &&
+ if((server->secureChannelStatistics.currentChannelCount >=
+ server->config.maxSecureChannels) &&
!purgeFirstChannelWithoutSession(server))
return UA_STATUSCODE_BADOUTOFMEMORY;
- UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_SECURECHANNEL,
- "Creating a new SecureChannel");
-
channel_entry *entry = (channel_entry *)UA_malloc(sizeof(channel_entry));
if(!entry)
return UA_STATUSCODE_BADOUTOFMEMORY;
@@ -38488,22 +41879,22 @@ UA_Server_createSecureChannel(UA_Server *server, UA_Connection *connection) {
/* TODO: Use the connection config from the correct network layer */
UA_SecureChannel_init(&entry->channel,
&server->config.networkLayers[0].localConnectionConfig);
- entry->channel.securityToken.channelId = 0;
- entry->channel.securityToken.createdAt = UA_DateTime_nowMonotonic();
- entry->channel.securityToken.revisedLifetime = server->config.maxSecurityTokenLifetime;
+ entry->channel.certificateVerification = &server->config.certificateVerification;
+ entry->channel.processOPNHeader = UA_Server_configSecureChannel;
TAILQ_INSERT_TAIL(&server->channels, entry, pointers);
UA_Connection_attachSecureChannel(connection, &entry->channel);
- UA_atomic_addSize(&server->serverStats.scs.currentChannelCount, 1);
- UA_atomic_addSize(&server->serverStats.scs.cumulatedChannelCount, 1);
+ server->secureChannelStatistics.currentChannelCount++;
+ server->secureChannelStatistics.cumulatedChannelCount++;
return UA_STATUSCODE_GOOD;
}
UA_StatusCode
-UA_Server_configSecureChannel(UA_Server *server, UA_SecureChannel *channel,
+UA_Server_configSecureChannel(void *application, UA_SecureChannel *channel,
const UA_AsymmetricAlgorithmSecurityHeader *asymHeader) {
/* Iterate over available endpoints and choose the correct one */
UA_SecurityPolicy *securityPolicy = NULL;
+ UA_Server *const server = (UA_Server *const) application;
for(size_t i = 0; i < server->config.securityPoliciesSize; ++i) {
UA_SecurityPolicy *policy = &server->config.securityPolicies[i];
if(!UA_ByteString_equal(&asymHeader->securityPolicyUri, &policy->policyUri))
@@ -38540,7 +41931,7 @@ static UA_StatusCode
UA_SecureChannelManager_open(UA_Server *server, UA_SecureChannel *channel,
const UA_OpenSecureChannelRequest *request,
UA_OpenSecureChannelResponse *response) {
- if(channel->state != UA_SECURECHANNELSTATE_CLOSED) {
+ if(channel->state != UA_SECURECHANNELSTATE_ACK_SENT) {
UA_LOG_ERROR_CHANNEL(&server->config.logger, channel,
"Called open on already open or closed channel");
return UA_STATUSCODE_BADINTERNALERROR;
@@ -38576,7 +41967,7 @@ UA_SecureChannelManager_open(UA_Server *server, UA_SecureChannel *channel,
* first symmetric messages is received. */
response->securityToken = channel->securityToken;
response->securityToken.createdAt = UA_DateTime_now(); /* Only for sending */
- response->responseHeader.timestamp = UA_DateTime_now();
+ response->responseHeader.timestamp = response->securityToken.createdAt;
response->responseHeader.requestHandle = request->requestHeader.requestHandle;
retval = UA_ByteString_copy(&channel->localNonce, &response->serverNonce);
if(retval != UA_STATUSCODE_GOOD)
@@ -38660,8 +42051,9 @@ Service_OpenSecureChannel(UA_Server *server, UA_SecureChannel *channel,
/* Logging */
if(response->responseHeader.serviceResult == UA_STATUSCODE_GOOD) {
- UA_LOG_DEBUG_CHANNEL(&server->config.logger, channel,
- "SecureChannel renewed");
+ UA_Float lifetime = (UA_Float)response->securityToken.revisedLifetime / 1000;
+ UA_LOG_INFO_CHANNEL(&server->config.logger, channel, "SecureChannel renewed "
+ "with a revised lifetime of %.2fs", lifetime);
} else {
UA_LOG_DEBUG_CHANNEL(&server->config.logger, channel,
"Renewing SecureChannel failed");
@@ -38681,8 +42073,12 @@ Service_OpenSecureChannel(UA_Server *server, UA_SecureChannel *channel,
/* Logging */
if(response->responseHeader.serviceResult == UA_STATUSCODE_GOOD) {
+ UA_Float lifetime = (UA_Float)response->securityToken.revisedLifetime / 1000;
UA_LOG_INFO_CHANNEL(&server->config.logger, channel,
- "Opened SecureChannel");
+ "SecureChannel opened with SecurityPolicy %.*s "
+ "and a revised lifetime of %.2fs",
+ (int)channel->securityPolicy->policyUri.length,
+ channel->securityPolicy->policyUri.data, lifetime);
} else {
UA_LOG_INFO_CHANNEL(&server->config.logger, channel,
"Opening a SecureChannel failed");
@@ -38697,7 +42093,7 @@ Service_CloseSecureChannel(UA_Server *server, UA_SecureChannel *channel) {
UA_DIAGNOSTICEVENT_CLOSE);
}
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/src/server/ua_services_nodemanagement.c" ***********************************/
+/**** amalgamated original file "/src/server/ua_services_nodemanagement.c" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -38714,10 +42110,17 @@ Service_CloseSecureChannel(UA_Server *server, UA_SecureChannel *channel) {
* Copyright 2017 (c) frax2222
* Copyright 2017-2018 (c) Stefan Profanter, fortiss GmbH
* Copyright 2017 (c) Christian von Arnim
+ * Copyright 2021 (c) Christian von Arnim, ISW University of Stuttgart (for VDW and umati)
* Copyright 2017 (c) Henrik Norrman
+ * Copyright 2021 (c) Fraunhofer IOSB (Author: Andreas Ebner)
*/
+static UA_StatusCode
+setMethodNode_callback(UA_Server *server,
+ const UA_NodeId methodNodeId,
+ UA_MethodCallback methodCallback);
+
/*********************/
/* Edit Node Context */
/*********************/
@@ -38725,55 +42128,65 @@ Service_CloseSecureChannel(UA_Server *server, UA_SecureChannel *channel) {
UA_StatusCode
UA_Server_getNodeContext(UA_Server *server, UA_NodeId nodeId,
void **nodeContext) {
- UA_LOCK(server->serviceMutex);
+ UA_LOCK(&server->serviceMutex);
UA_StatusCode retval = getNodeContext(server, nodeId, nodeContext);
- UA_UNLOCK(server->serviceMutex);
+ UA_UNLOCK(&server->serviceMutex);
return retval;
}
UA_StatusCode
getNodeContext(UA_Server *server, UA_NodeId nodeId,
- void **nodeContext) {
+ void **nodeContext) {
const UA_Node *node = UA_NODESTORE_GET(server, &nodeId);
if(!node)
return UA_STATUSCODE_BADNODEIDUNKNOWN;
- *nodeContext = node->context;
+ *nodeContext = node->head.context;
UA_NODESTORE_RELEASE(server, node);
return UA_STATUSCODE_GOOD;
}
static UA_StatusCode
setDeconstructedNode(UA_Server *server, UA_Session *session,
- UA_Node *node, void *context) {
- node->constructed = false;
+ UA_NodeHead *head, void *context) {
+ head->constructed = false;
return UA_STATUSCODE_GOOD;
}
static UA_StatusCode
setConstructedNodeContext(UA_Server *server, UA_Session *session,
- UA_Node *node, void *context) {
- node->context = context;
- node->constructed = true;
+ UA_NodeHead *head, void *context) {
+ head->context = context;
+ head->constructed = true;
return UA_STATUSCODE_GOOD;
}
static UA_StatusCode
editNodeContext(UA_Server *server, UA_Session* session,
- UA_Node* node, void *context) {
- node->context = context;
+ UA_NodeHead *head, void *context) {
+ head->context = context;
return UA_STATUSCODE_GOOD;
}
UA_StatusCode
+setNodeContext(UA_Server *server, UA_NodeId nodeId,
+ void *nodeContext) {
+ return UA_Server_editNode(server, &server->adminSession, &nodeId,
+ (UA_EditNodeCallback)editNodeContext, nodeContext);
+}
+
+UA_StatusCode
UA_Server_setNodeContext(UA_Server *server, UA_NodeId nodeId,
void *nodeContext) {
- UA_LOCK(server->serviceMutex);
- UA_StatusCode retval = UA_Server_editNode(server, &server->adminSession, &nodeId,
- (UA_EditNodeCallback)editNodeContext, nodeContext);
- UA_UNLOCK(server->serviceMutex);
+ UA_LOCK(&server->serviceMutex);
+ UA_StatusCode retval = setNodeContext(server, nodeId, nodeContext);
+ UA_UNLOCK(&server->serviceMutex);
return retval;
}
+static UA_StatusCode
+checkSetIsDynamicVariable(UA_Server *server, UA_Session *session,
+ const UA_NodeId *nodeId);
+
/**********************/
/* Consistency Checks */
/**********************/
@@ -38785,85 +42198,92 @@ const UA_NodeId parentReferences[UA_PARENT_REFERENCES_COUNT] = {
{0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_HASCOMPONENT}}
};
+static void
+logAddNode(const UA_Logger *logger, UA_Session *session,
+ const UA_NodeId *nodeId, const char *msg) {
+ UA_LOG_NODEID_INFO(nodeId,
+ UA_LOG_INFO_SESSION(logger, session, "AddNode (%.*s): %s",
+ (int)nodeIdStr.length, nodeIdStr.data, msg));
+}
+
/* Check if the requested parent node exists, has the right node class and is
* referenced with an allowed (hierarchical) reference type. For "type" nodes,
* only hasSubType references are allowed. */
static UA_StatusCode
-checkParentReference(UA_Server *server, UA_Session *session, UA_NodeClass nodeClass,
+checkParentReference(UA_Server *server, UA_Session *session, const UA_NodeHead *head,
const UA_NodeId *parentNodeId, const UA_NodeId *referenceTypeId) {
- /* Objects do not need a parent (e.g. mandatory/optional modellingrules) */
- /* Also, there are some variables which do not have parents, e.g. EnumStrings, EnumValues */
- if((nodeClass == UA_NODECLASS_OBJECT || nodeClass == UA_NODECLASS_VARIABLE) &&
+ /* Objects do not need a parent (e.g. mandatory/optional modellingrules).
+ * Also, there are some variables which do not have parents, e.g.
+ * EnumStrings, EnumValues */
+ if((head->nodeClass == UA_NODECLASS_OBJECT ||
+ head->nodeClass == UA_NODECLASS_VARIABLE) &&
UA_NodeId_isNull(parentNodeId) && UA_NodeId_isNull(referenceTypeId))
return UA_STATUSCODE_GOOD;
/* See if the parent exists */
const UA_Node *parent = UA_NODESTORE_GET(server, parentNodeId);
if(!parent) {
- UA_LOG_NODEID_WRAP(parentNodeId, UA_LOG_INFO_SESSION(&server->config.logger, session,
- "AddNodes: Parent node %.*s not found",
- (int)nodeIdStr.length, nodeIdStr.data));
+ logAddNode(&server->config.logger, session, &head->nodeId,
+ "Parent node not found");
return UA_STATUSCODE_BADPARENTNODEIDINVALID;
}
- UA_NodeClass parentNodeClass = parent->nodeClass;
+ UA_NodeClass parentNodeClass = parent->head.nodeClass;
UA_NODESTORE_RELEASE(server, parent);
/* Check the referencetype exists */
- const UA_ReferenceTypeNode *referenceType = (const UA_ReferenceTypeNode*)
- UA_NODESTORE_GET(server, referenceTypeId);
+ const UA_Node *referenceType = UA_NODESTORE_GET(server, referenceTypeId);
if(!referenceType) {
- UA_LOG_NODEID_WRAP(referenceTypeId, UA_LOG_INFO_SESSION(&server->config.logger, session,
- "AddNodes: Reference type %.*s to the parent not found",
- (int)nodeIdStr.length, nodeIdStr.data));
+ logAddNode(&server->config.logger, session, &head->nodeId,
+ "Reference type to the parent not found");
return UA_STATUSCODE_BADREFERENCETYPEIDINVALID;
}
/* Check if the referencetype is a reference type node */
- if(referenceType->nodeClass != UA_NODECLASS_REFERENCETYPE) {
- UA_LOG_NODEID_WRAP(referenceTypeId, UA_LOG_INFO_SESSION(&server->config.logger, session,
- "AddNodes: Reference type %.*s to the parent is not a ReferenceTypeNode",
- (int)nodeIdStr.length, nodeIdStr.data));
- UA_NODESTORE_RELEASE(server, (const UA_Node*)referenceType);
+ if(referenceType->head.nodeClass != UA_NODECLASS_REFERENCETYPE) {
+ logAddNode(&server->config.logger, session, &head->nodeId,
+ "Reference type to the parent is not a ReferenceTypeNode");
+ UA_NODESTORE_RELEASE(server, referenceType);
return UA_STATUSCODE_BADREFERENCETYPEIDINVALID;
}
- UA_Boolean referenceTypeIsAbstract = referenceType->isAbstract;
- UA_NODESTORE_RELEASE(server, (const UA_Node*)referenceType);
/* Check that the reference type is not abstract */
+ UA_Boolean referenceTypeIsAbstract = referenceType->referenceTypeNode.isAbstract;
+ UA_NODESTORE_RELEASE(server, referenceType);
if(referenceTypeIsAbstract == true) {
- UA_LOG_NODEID_WRAP(referenceTypeId, UA_LOG_INFO_SESSION(&server->config.logger, session,
- "AddNodes: Abstract reference type %.*s to the parent not allowed",
- (int)nodeIdStr.length, nodeIdStr.data));
+ logAddNode(&server->config.logger, session, &head->nodeId,
+ "Abstract reference type to the parent not allowed");
return UA_STATUSCODE_BADREFERENCENOTALLOWED;
}
/* Check hassubtype relation for type nodes */
- if(nodeClass == UA_NODECLASS_DATATYPE ||
- nodeClass == UA_NODECLASS_VARIABLETYPE ||
- nodeClass == UA_NODECLASS_OBJECTTYPE ||
- nodeClass == UA_NODECLASS_REFERENCETYPE) {
- /* type needs hassubtype reference to the supertype */
- if(!UA_NodeId_equal(referenceTypeId, &subtypeId)) {
- UA_LOG_INFO_SESSION(&server->config.logger, session,
- "AddNodes: Type nodes need to have a HasSubType "
- "reference to the parent");
+ if(head->nodeClass == UA_NODECLASS_DATATYPE ||
+ head->nodeClass == UA_NODECLASS_VARIABLETYPE ||
+ head->nodeClass == UA_NODECLASS_OBJECTTYPE ||
+ head->nodeClass == UA_NODECLASS_REFERENCETYPE) {
+ /* Type needs hassubtype reference to the supertype */
+ if(referenceType->referenceTypeNode.referenceTypeIndex !=
+ UA_REFERENCETYPEINDEX_HASSUBTYPE) {
+ logAddNode(&server->config.logger, session, &head->nodeId,
+ "Type nodes need to have a HasSubType reference to the parent");
return UA_STATUSCODE_BADREFERENCENOTALLOWED;
}
- /* supertype needs to be of the same node type */
- if(parentNodeClass != nodeClass) {
- UA_LOG_INFO_SESSION(&server->config.logger, session,
- "AddNodes: Type nodes needs to be of the same node "
- "type as their parent");
+ /* Supertype needs to be of the same node type */
+ if(parentNodeClass != head->nodeClass) {
+ logAddNode(&server->config.logger, session, &head->nodeId,
+ "Type nodes needs to be of the same node "
+ "type as their parent");
return UA_STATUSCODE_BADPARENTNODEIDINVALID;
}
return UA_STATUSCODE_GOOD;
}
/* Test if the referencetype is hierarchical */
- if(!isNodeInTree(server, referenceTypeId, &hierarchicalReferences, &subtypeId, 1)) {
- UA_LOG_INFO_SESSION(&server->config.logger, session,
- "AddNodes: Reference type to the parent is not hierarchical");
+ const UA_NodeId hierarchRefs = UA_NODEID_NUMERIC(0, UA_NS0ID_HIERARCHICALREFERENCES);
+ if(!isNodeInTree_singleRef(server, referenceTypeId, &hierarchRefs,
+ UA_REFERENCETYPEINDEX_HASSUBTYPE)) {
+ logAddNode(&server->config.logger, session, &head->nodeId,
+ "Reference type to the parent is not hierarchical");
return UA_STATUSCODE_BADREFERENCETYPEIDINVALID;
}
@@ -38871,81 +42291,193 @@ checkParentReference(UA_Server *server, UA_Session *session, UA_NodeClass nodeCl
}
static UA_StatusCode
+setDefaultValue(UA_Server *server, const UA_VariableNode *node) {
+ /* Get the DataType */
+ UA_StatusCode res = UA_STATUSCODE_GOOD;
+ const UA_DataType *type = UA_Server_findDataType(server, &node->dataType);
+ if(!type) {
+ /* No description for the DataType found. It is possible that an
+ * abstract DataType is used, e.g. UInteger. Browse to see if there is a
+ * non-abstract subtype that can be used for the default value.
+ *
+ * Look up and downwards in the hierarchy. Some data types (e.g.
+ * UtcTime) are derived from a non-abstract data type. This is then used
+ * for the actual value, Use the first match. */
+ UA_ReferenceTypeSet refs = UA_REFTYPESET(UA_REFERENCETYPEINDEX_HASSUBTYPE);
+ UA_ExpandedNodeId *typeCandidates = NULL;
+ size_t typeCandidatesSize = 0;
+ res = browseRecursive(server, 1, &node->dataType,
+ UA_BROWSEDIRECTION_BOTH, &refs,
+ UA_NODECLASS_DATATYPE, false,
+ &typeCandidatesSize, &typeCandidates);
+ if(res != UA_STATUSCODE_GOOD)
+ return res;
+
+ for(size_t i = 0; i < typeCandidatesSize; i++) {
+ /* Skip BaseDataType (Variant). This is the root of the DataType
+ * hierarchy. Variables of BaseDataType can be empty. */
+ if(UA_NodeId_equal(&UA_TYPES[UA_TYPES_VARIANT].typeId,
+ &typeCandidates[i].nodeId))
+ continue;
+ type = UA_Server_findDataType(server, &typeCandidates[i].nodeId);
+ if(type)
+ break;
+ }
+
+ UA_Array_delete(typeCandidates, typeCandidatesSize,
+ &UA_TYPES[UA_TYPES_EXPANDEDNODEID]);
+ if(!type)
+ return UA_STATUSCODE_BADTYPEMISMATCH;
+ }
+
+ /* Set up the value with the default content */
+ UA_Variant val;
+ UA_Variant_init(&val);
+ if(node->valueRank < 0) {
+ /* Set a scalar */
+ void *data = UA_new(type);
+ if(!data)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ UA_Variant_setScalar(&val, data, type);
+ } else if(node->valueRank == 0) {
+ /* Use an empty array of one dimension */
+ UA_Variant_setArray(&val, NULL, 0, type);
+ } else {
+ /* Write an array that matches the ArrayDimensions */
+ res = UA_Array_copy(node->arrayDimensions, node->arrayDimensionsSize,
+ (void**)&val.arrayDimensions, &UA_TYPES[UA_TYPES_UINT32]);
+ if(res != UA_STATUSCODE_GOOD)
+ return res;
+ val.arrayDimensionsSize = node->arrayDimensionsSize;
+
+ /* No length restriction in the ArrayDimension -> use length 1 */
+ size_t size = 1;
+ for(size_t i = 0; i < val.arrayDimensionsSize; i++) {
+ if(val.arrayDimensions[i] == 0)
+ val.arrayDimensions[i] = 1;
+ size *= val.arrayDimensions[i];
+ }
+
+ /* Create the content array */
+ void *data = UA_Array_new(size, type);
+ if(!data) {
+ UA_Variant_clear(&val);
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ }
+
+ val.data = data;
+ val.arrayLength = size;
+ val.type = type;
+ }
+
+ /* Write the value */
+ res = writeAttribute(server, &server->adminSession, &node->head.nodeId,
+ UA_ATTRIBUTEID_VALUE, &val, &UA_TYPES[UA_TYPES_VARIANT]);
+
+ /* Clean up */
+ UA_Variant_clear(&val);
+ return res;
+}
+
+static UA_StatusCode
typeCheckVariableNode(UA_Server *server, UA_Session *session,
const UA_VariableNode *node,
const UA_VariableTypeNode *vt) {
- /* The value might come from a datasource, so we perform a
- * regular read. */
- UA_DataValue value;
- UA_DataValue_init(&value);
- UA_StatusCode retval = readValueAttribute(server, session, node, &value);
- if(retval != UA_STATUSCODE_GOOD)
- return retval;
-
- UA_NodeId baseDataType = UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATATYPE);
-
/* Check the datatype against the vt */
- /* If the node does not have any value and the dataType is BaseDataType,
- * then it's also fine. This is the default for empty nodes. */
- if(!compatibleDataType(server, &node->dataType, &vt->dataType, false) &&
- (value.hasValue || !UA_NodeId_equal(&node->dataType, &baseDataType))) {
- UA_LOG_NODEID_WRAP(&node->nodeId, UA_LOG_INFO_SESSION(&server->config.logger, session,
- "AddNodes: The value of %.*s is incompatible with "
- "the datatype of the VariableType",
- (int)nodeIdStr.length, nodeIdStr.data));
- UA_DataValue_clear(&value);
+ if(!compatibleDataTypes(server, &node->dataType, &vt->dataType)) {
+ logAddNode(&server->config.logger, session, &node->head.nodeId,
+ "The value of is incompatible with "
+ "the datatype of the VariableType");
return UA_STATUSCODE_BADTYPEMISMATCH;
}
/* Check valueRank against array dimensions */
if(!compatibleValueRankArrayDimensions(server, session, node->valueRank,
node->arrayDimensionsSize)) {
- UA_LOG_NODEID_WRAP(&node->nodeId, UA_LOG_INFO_SESSION(&server->config.logger, session,
- "AddNodes: The value rank of %.*s is incompatible "
- "with its array dimensions", (int)nodeIdStr.length, nodeIdStr.data));
- UA_DataValue_clear(&value);
+ logAddNode(&server->config.logger, session, &node->head.nodeId,
+ "The value rank of is incompatible with its array dimensions");
return UA_STATUSCODE_BADTYPEMISMATCH;
}
/* Check valueRank against the vt */
if(!compatibleValueRanks(node->valueRank, vt->valueRank)) {
- UA_LOG_NODEID_WRAP(&node->nodeId, UA_LOG_INFO_SESSION(&server->config.logger, session,
- "AddNodes: The value rank of %.*s is incompatible "
- "with the value rank of the VariableType",
- (int)nodeIdStr.length, nodeIdStr.data));
- UA_DataValue_clear(&value);
+ logAddNode(&server->config.logger, session, &node->head.nodeId,
+ "The value rank is incompatible "
+ "with the value rank of the VariableType");
return UA_STATUSCODE_BADTYPEMISMATCH;
}
/* Check array dimensions against the vt */
if(!compatibleArrayDimensions(vt->arrayDimensionsSize, vt->arrayDimensions,
node->arrayDimensionsSize, node->arrayDimensions)) {
- UA_LOG_NODEID_WRAP(&node->nodeId, UA_LOG_INFO_SESSION(&server->config.logger, session,
- "AddNodes: The array dimensions of %.*s are "
- "incompatible with the array dimensions of the VariableType",
- (int)nodeIdStr.length, nodeIdStr.data));
- UA_DataValue_clear(&value);
+ logAddNode(&server->config.logger, session, &node->head.nodeId,
+ "The array dimensions are incompatible with the "
+ "array dimensions of the VariableType");
return UA_STATUSCODE_BADTYPEMISMATCH;
}
/* Typecheck the value */
- if(value.hasValue && value.value.data) {
- /* If the type-check failed write the same value again. The
- * write-service tries to convert to the correct type... */
- if(!compatibleValue(server, session, &node->dataType, node->valueRank,
- node->arrayDimensionsSize, node->arrayDimensions,
- &value.value, NULL)) {
- retval = writeWithWriteValue(server, &node->nodeId, UA_ATTRIBUTEID_VALUE, &UA_TYPES[UA_TYPES_VARIANT], &value.value);
+
+ /* The value might come from a datasource, so we perform a
+ * regular read. */
+ UA_DataValue value;
+ UA_DataValue_init(&value);
+ UA_StatusCode retval = readValueAttribute(server, session, node, &value);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+
+ /* Only BaseDataType (Variant) can have empty values. Create default content
+ * otherwise that matches the constraints. */
+ if(!value.hasValue || !value.value.type) {
+ if(!UA_NodeId_equal(&node->dataType, &UA_TYPES[UA_TYPES_VARIANT].typeId)) {
+ /* Warn if that is configured */
+ if(!server->bootstrapNS0 &&
+ server->config.allowEmptyVariables != UA_RULEHANDLING_ACCEPT)
+ logAddNode(&server->config.logger, session, &node->head.nodeId,
+ "The value is empty. But this is only allowed for BaseDataType. "
+ "Create a matching default value.");
+
+ /* Abort if that is configured */
+ if(server->config.allowEmptyVariables == UA_RULEHANDLING_ABORT)
+ retval = UA_STATUSCODE_BADTYPEMISMATCH;
+
+ /* Try to generate a default value if that is configured */
+ if(server->config.allowEmptyVariables == UA_RULEHANDLING_DEFAULT) {
+ retval = setDefaultValue(server, node);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_LOG_NODEID_INFO(&node->head.nodeId,
+ UA_LOG_INFO_SESSION(&server->config.logger, session,
+ "AddNode (%.*s): Could not create a default value "
+ "with StatusCode %s", (int)nodeIdStr.length,
+ nodeIdStr.data, UA_StatusCode_name(retval)));
+ }
+
+ /* Reread the current value for compat tests below */
+ UA_DataValue_clear(&value);
+ retval = readValueAttribute(server, session, node, &value);
+ }
}
- UA_DataValue_clear(&value);
if(retval != UA_STATUSCODE_GOOD) {
- UA_LOG_NODEID_WRAP(&node->nodeId, UA_LOG_INFO_SESSION(&server->config.logger, session,
- "AddNodes: The value of %.*s is incompatible with the "
- "variable definition", (int)nodeIdStr.length, nodeIdStr.data));
+ UA_DataValue_clear(&value);
+ return retval;
+ }
+ }
+
+ /* Perform the value typecheck. If this fails, write the current value
+ * again. The write-service tries to convert to the correct type... */
+ const char *reason;
+ if(!compatibleValue(server, session, &node->dataType, node->valueRank,
+ node->arrayDimensionsSize, node->arrayDimensions,
+ &value.value, NULL, &reason)) {
+ retval = writeValueAttribute(server, session, &node->head.nodeId, &value.value);
+ if(retval != UA_STATUSCODE_GOOD) {
+ logAddNode(&server->config.logger, session, &node->head.nodeId,
+ "The value is incompatible with the variable definition");
}
}
+ UA_DataValue_clear(&value);
return retval;
}
@@ -38964,84 +42496,62 @@ static const UA_NodeId hasTypeDefinition =
* changes were made. */
static UA_StatusCode
useVariableTypeAttributes(UA_Server *server, UA_Session *session,
- const UA_VariableNode **node_ptr,
+ const UA_VariableNode *node,
const UA_VariableTypeNode *vt) {
- const UA_VariableNode *node = *node_ptr;
- UA_Boolean modified = false;
-
/* If no value is set, see if the vt provides one and copy it. This needs to
* be done before copying the datatype from the vt, as setting the datatype
* triggers a typecheck. */
- UA_DataValue orig;
- UA_DataValue_init(&orig);
- UA_StatusCode retval = readValueAttribute(server, session, node, &orig);
+ UA_Variant orig;
+ UA_StatusCode retval =
+ readWithReadValue(server, &node->head.nodeId, UA_ATTRIBUTEID_VALUE, &orig);
if(retval != UA_STATUSCODE_GOOD)
return retval;
- if(orig.value.type) {
+ if(orig.type) {
/* A value is present */
- UA_DataValue_clear(&orig);
+ UA_Variant_clear(&orig);
} else {
- UA_WriteValue v;
- UA_WriteValue_init(&v);
- retval = readValueAttribute(server, session, (const UA_VariableNode*)vt, &v.value);
- if(retval == UA_STATUSCODE_GOOD && v.value.hasValue) {
- v.nodeId = node->nodeId;
- v.attributeId = UA_ATTRIBUTEID_VALUE;
- retval = writeWithSession(server, session, &v);
- modified = true;
- }
- UA_DataValue_clear(&v.value);
- if(retval != UA_STATUSCODE_GOOD)
- return retval;
+ UA_DataValue v;
+ UA_DataValue_init(&v);
+ retval = readValueAttribute(server, session, (const UA_VariableNode*)vt, &v);
+ if(retval == UA_STATUSCODE_GOOD && v.hasValue) {
+ retval = writeValueAttribute(server, session, &node->head.nodeId, &v.value);
+ }
+ UA_DataValue_clear(&v);
+
+ if(retval != UA_STATUSCODE_GOOD) {
+ logAddNode(&server->config.logger, session, &node->head.nodeId,
+ "The default content of the VariableType could "
+ "not be used. This may happen if the VariableNode "
+ "makes additional restrictions.");
+ retval = UA_STATUSCODE_GOOD;
+ }
}
/* If no datatype is given, use the datatype of the vt */
if(UA_NodeId_isNull(&node->dataType)) {
- UA_LOG_INFO_SESSION(&server->config.logger, session, "AddNodes: "
- "No datatype given; Copy the datatype attribute "
- "from the TypeDefinition");
- UA_WriteValue v;
- UA_WriteValue_init(&v);
- v.nodeId = node->nodeId;
- v.attributeId = UA_ATTRIBUTEID_DATATYPE;
- v.value.hasValue = true;
- UA_Variant_setScalar(&v.value.value, (void*)(uintptr_t)&vt->dataType,
- &UA_TYPES[UA_TYPES_NODEID]);
- retval = writeWithSession(server, session, &v);
- modified = true;
+ logAddNode(&server->config.logger, session, &node->head.nodeId,
+ "No datatype given; Copy the datatype attribute "
+ "from the TypeDefinition");
+ retval = writeAttribute(server, session, &node->head.nodeId,
+ UA_ATTRIBUTEID_DATATYPE, &vt->dataType,
+ &UA_TYPES[UA_TYPES_NODEID]);
if(retval != UA_STATUSCODE_GOOD)
return retval;
}
/* Use the ArrayDimensions of the vt */
if(node->arrayDimensionsSize == 0 && vt->arrayDimensionsSize > 0) {
- UA_WriteValue v;
- UA_WriteValue_init(&v);
- v.nodeId = node->nodeId;
- v.attributeId = UA_ATTRIBUTEID_ARRAYDIMENSIONS;
- v.value.hasValue = true;
- UA_Variant_setArray(&v.value.value, vt->arrayDimensions,
- vt->arrayDimensionsSize, &UA_TYPES[UA_TYPES_UINT32]);
- retval = writeWithSession(server, session, &v);
- modified = true;
- if(retval != UA_STATUSCODE_GOOD)
- return retval;
- }
-
- /* If the node was modified, update the pointer to the new version */
- if(modified) {
- const UA_VariableNode *updated = (const UA_VariableNode*)
- UA_NODESTORE_GET(server, &node->nodeId);
-
- if(!updated)
- return UA_STATUSCODE_BADINTERNALERROR;
-
- UA_NODESTORE_RELEASE(server, (const UA_Node*)node);
- *node_ptr = updated;
+ UA_Variant v;
+ UA_Variant_init(&v);
+ UA_Variant_setArray(&v, vt->arrayDimensions, vt->arrayDimensionsSize,
+ &UA_TYPES[UA_TYPES_UINT32]);
+ retval = writeAttribute(server, session, &node->head.nodeId,
+ UA_ATTRIBUTEID_ARRAYDIMENSIONS, &v,
+ &UA_TYPES[UA_TYPES_VARIANT]);
}
- return UA_STATUSCODE_GOOD;
+ return retval;
}
/* Search for an instance of "browseName" in node searchInstance. Used during
@@ -39084,8 +42594,6 @@ findChildByBrowsename(UA_Server *server, UA_Session *session,
static const UA_NodeId mandatoryId =
{0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_MODELLINGRULE_MANDATORY}};
-static const UA_NodeId hasModellingRuleId =
- {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_HASMODELLINGRULE}};
static UA_Boolean
isMandatoryChild(UA_Server *server, UA_Session *session,
@@ -39096,14 +42604,17 @@ isMandatoryChild(UA_Server *server, UA_Session *session,
return false;
/* Look for the reference making the child mandatory */
- for(size_t i = 0; i < child->referencesSize; ++i) {
- UA_NodeReferenceKind *refs = &child->references[i];
- if(!UA_NodeId_equal(&hasModellingRuleId, &refs->referenceTypeId))
+ UA_NodePointer mandatoryP = UA_NodePointer_fromNodeId(&mandatoryId);
+ for(size_t i = 0; i < child->head.referencesSize; ++i) {
+ UA_NodeReferenceKind *rk = &child->head.references[i];
+ if(rk->referenceTypeIndex != UA_REFERENCETYPEINDEX_HASMODELLINGRULE)
continue;
- if(refs->isInverse)
+ if(rk->isInverse)
continue;
- for(size_t j = 0; j < refs->refTargetsSize; ++j) {
- if(UA_NodeId_equal(&mandatoryId, &refs->refTargets[j].targetId.nodeId)) {
+
+ const UA_ReferenceTarget *t = NULL;
+ while((t = UA_NodeReferenceKind_iterate(rk, t))) {
+ if(UA_NodePointer_equal(mandatoryP, t->targetId)) {
UA_NODESTORE_RELEASE(server, child);
return true;
}
@@ -39118,17 +42629,68 @@ static UA_StatusCode
copyAllChildren(UA_Server *server, UA_Session *session,
const UA_NodeId *source, const UA_NodeId *destination);
-static UA_StatusCode
-recursiveTypeCheckAddChildren(UA_Server *server, UA_Session *session,
- const UA_Node **node, const UA_Node *type);
-
static void
Operation_addReference(UA_Server *server, UA_Session *session, void *context,
const UA_AddReferencesItem *item, UA_StatusCode *retval);
+UA_StatusCode
+addRef(UA_Server *server, UA_Session *session, const UA_NodeId *sourceId,
+ const UA_NodeId *referenceTypeId, const UA_NodeId *targetId,
+ UA_Boolean forward) {
+ UA_AddReferencesItem ref_item;
+ UA_AddReferencesItem_init(&ref_item);
+ ref_item.sourceNodeId = *sourceId;
+ ref_item.referenceTypeId = *referenceTypeId;
+ ref_item.isForward = forward;
+ ref_item.targetNodeId.nodeId = *targetId;
+
+ UA_StatusCode retval = UA_STATUSCODE_GOOD;
+ Operation_addReference(server, session, NULL, &ref_item, &retval);
+ return retval;
+}
+
static UA_StatusCode
-copyChild(UA_Server *server, UA_Session *session, const UA_NodeId *destinationNodeId,
+addInterfaceChildren(UA_Server *server, UA_Session *session,
+ const UA_NodeId *nodeId, const UA_NodeId *typeId) {
+ /* Get the hierarchy of the type and all its supertypes */
+ UA_NodeId *hierarchy = NULL;
+ size_t hierarchySize = 0;
+ UA_StatusCode retval = getAllInterfaceChildNodeIds(server, nodeId, typeId,
+ &hierarchy, &hierarchySize);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+
+ /* Copy members of the type and supertypes (and instantiate them) */
+ for(size_t i = 0; i < hierarchySize; ++i) {
+ retval = copyAllChildren(server, session, &hierarchy[i], nodeId);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_Array_delete(hierarchy, hierarchySize, &UA_TYPES[UA_TYPES_NODEID]);
+ return retval;
+ }
+ }
+
+ for(size_t i = 0; i < hierarchySize; ++i) {
+ UA_NodeId refId = UA_NODEID_NUMERIC(0, UA_NS0ID_HASINTERFACE);
+ retval = addRef(server, &server->adminSession, nodeId, &refId, &hierarchy[i], true);
+
+ /* Don't add the original HasInterface reference to ObjectType sub nodes */
+ if(retval == UA_STATUSCODE_BADDUPLICATEREFERENCENOTALLOWED) {
+ retval = UA_STATUSCODE_GOOD;
+ } else if(retval != UA_STATUSCODE_GOOD) {
+ break;
+ }
+ }
+
+ UA_Array_delete(hierarchy, hierarchySize, &UA_TYPES[UA_TYPES_NODEID]);
+ return retval;
+}
+
+static UA_StatusCode
+copyChild(UA_Server *server, UA_Session *session,
+ const UA_NodeId *destinationNodeId,
const UA_ReferenceDescription *rd) {
+ UA_assert(session);
+
/* Is there an existing child with the browsename? */
UA_NodeId existingChild = UA_NODEID_NULL;
UA_StatusCode retval = findChildByBrowsename(server, session, destinationNodeId,
@@ -39150,18 +42712,13 @@ copyChild(UA_Server *server, UA_Session *session, const UA_NodeId *destinationNo
if(!isMandatoryChild(server, session, &rd->nodeId.nodeId)) {
if(!server->config.nodeLifecycle.createOptionalChild)
return UA_STATUSCODE_GOOD;
-
- UA_UNLOCK(server->serviceMutex);
- retval = server->config.nodeLifecycle.createOptionalChild(server,
- &session->sessionId,
- session->sessionHandle,
- &rd->nodeId.nodeId,
- destinationNodeId,
- &rd->referenceTypeId);
- UA_LOCK(server->serviceMutex);
- if(retval == UA_FALSE) {
+ UA_UNLOCK(&server->serviceMutex);
+ UA_Boolean createChild = server->config.nodeLifecycle.
+ createOptionalChild(server, &session->sessionId, session->sessionHandle,
+ &rd->nodeId.nodeId, destinationNodeId, &rd->referenceTypeId);
+ UA_LOCK(&server->serviceMutex);
+ if(!createChild)
return UA_STATUSCODE_GOOD;
- }
}
/* Child is a method -> create a reference */
@@ -39187,40 +42744,54 @@ copyChild(UA_Server *server, UA_Session *session, const UA_NodeId *destinationNo
return retval;
/* Remove the context of the copied node */
- node->context = NULL;
- node->constructed = false;
+ node->head.context = NULL;
+ node->head.constructed = false;
+#ifdef UA_ENABLE_SUBSCRIPTIONS
+ node->head.monitoredItems = NULL;
+#endif
/* Reset the NodeId (random numeric id will be assigned in the nodestore) */
- UA_NodeId_clear(&node->nodeId);
- node->nodeId.namespaceIndex = destinationNodeId->namespaceIndex;
-
- if (server->config.nodeLifecycle.generateChildNodeId) {
- UA_UNLOCK(server->serviceMutex);
- retval = server->config.nodeLifecycle.generateChildNodeId(server,
- &session->sessionId, session->sessionHandle,
- &rd->nodeId.nodeId,
- destinationNodeId,
- &rd->referenceTypeId,
- &node->nodeId);
- UA_LOCK(server->serviceMutex);
+ UA_NodeId_clear(&node->head.nodeId);
+ node->head.nodeId.namespaceIndex = destinationNodeId->namespaceIndex;
+
+ if(server->config.nodeLifecycle.generateChildNodeId) {
+ UA_UNLOCK(&server->serviceMutex);
+ retval = server->config.nodeLifecycle.
+ generateChildNodeId(server, &session->sessionId, session->sessionHandle,
+ &rd->nodeId.nodeId, destinationNodeId,
+ &rd->referenceTypeId, &node->head.nodeId);
+ UA_LOCK(&server->serviceMutex);
if(retval != UA_STATUSCODE_GOOD) {
UA_NODESTORE_DELETE(server, node);
return retval;
}
}
-
/* Remove references, they are re-created from scratch in addnode_finish */
/* TODO: Be more clever in removing references that are re-added during
* addnode_finish. That way, we can call addnode_finish also on children that were
* manually added by the user during addnode_begin and addnode_finish. */
/* For now we keep all the modelling rule references and delete all others */
- UA_NodeId modellingRuleReferenceId = UA_NODEID_NUMERIC(0, UA_NS0ID_HASMODELLINGRULE);
- UA_Node_deleteReferencesSubset(node, 1, &modellingRuleReferenceId);
+ const UA_NodeId nodeId_typesFolder= UA_NODEID_NUMERIC(0, UA_NS0ID_TYPESFOLDER);
+ const UA_ReferenceTypeSet reftypes_aggregates =
+ UA_REFTYPESET(UA_REFERENCETYPEINDEX_AGGREGATES);
+ UA_ReferenceTypeSet reftypes_skipped;
+ /* Check if the hasModellingRule-reference is required (configured or node in an
+ instance declaration) */
+ if(server->config.modellingRulesOnInstances ||
+ isNodeInTree(server, destinationNodeId,
+ &nodeId_typesFolder, &reftypes_aggregates)) {
+ reftypes_skipped = UA_REFTYPESET(UA_REFERENCETYPEINDEX_HASMODELLINGRULE);
+ } else {
+ UA_ReferenceTypeSet_init(&reftypes_skipped);
+ }
+ reftypes_skipped = UA_ReferenceTypeSet_union(reftypes_skipped, UA_REFTYPESET(UA_REFERENCETYPEINDEX_HASINTERFACE));
+ UA_Node_deleteReferencesSubset(node, &reftypes_skipped);
/* Add the node to the nodestore */
UA_NodeId newNodeId;
retval = UA_NODESTORE_INSERT(server, node, &newNodeId);
+ /* node = NULL; The pointer is no longer valid */
if(retval != UA_STATUSCODE_GOOD)
return retval;
@@ -39229,13 +42800,39 @@ copyChild(UA_Server *server, UA_Session *session, const UA_NodeId *destinationNo
&rd->referenceTypeId, &rd->typeDefinition.nodeId);
if(retval != UA_STATUSCODE_GOOD) {
UA_NODESTORE_REMOVE(server, &newNodeId);
+ UA_NodeId_clear(&newNodeId);
return retval;
}
+ if (rd->nodeClass == UA_NODECLASS_VARIABLE) {
+ retval = checkSetIsDynamicVariable(server, session, &newNodeId);
+
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_NODESTORE_REMOVE(server, &newNodeId);
+ return retval;
+ }
+ }
+
/* For the new child, recursively copy the members of the original. No
* typechecking is performed here. Assuming that the original is
* consistent. */
retval = copyAllChildren(server, session, &rd->nodeId.nodeId, &newNodeId);
+ if(retval != UA_STATUSCODE_GOOD) {
+ deleteNode(server, newNodeId, true);
+ return retval;
+ }
+
+ /* Check if its a dynamic variable, add all type and/or interface
+ * children and call the constructor */
+ retval = AddNode_finish(server, session, &newNodeId);
+ if(retval != UA_STATUSCODE_GOOD) {
+ deleteNode(server, newNodeId, true);
+ return retval;
+ }
+
+ /* Clean up. Because it can happen that a string is assigned as ID at
+ * generateChildNodeId. */
+ UA_NodeId_clear(&newNodeId);
}
return retval;
@@ -39268,7 +42865,7 @@ copyAllChildren(UA_Server *server, UA_Session *session,
UA_ReferenceDescription *rd = &br.references[i];
retval = copyChild(server, session, destination, rd);
if(retval != UA_STATUSCODE_GOOD)
- return retval;
+ break;
}
UA_BrowseResult_clear(&br);
@@ -39277,11 +42874,11 @@ copyAllChildren(UA_Server *server, UA_Session *session,
static UA_StatusCode
addTypeChildren(UA_Server *server, UA_Session *session,
- const UA_Node *node, const UA_Node *type) {
+ const UA_NodeId *nodeId, const UA_NodeId *typeId) {
/* Get the hierarchy of the type and all its supertypes */
UA_NodeId *hierarchy = NULL;
size_t hierarchySize = 0;
- UA_StatusCode retval = getParentTypeAndInterfaceHierarchy(server, &type->nodeId,
+ UA_StatusCode retval = getParentTypeAndInterfaceHierarchy(server, typeId,
&hierarchy, &hierarchySize);
if(retval != UA_STATUSCODE_GOOD)
return retval;
@@ -39289,7 +42886,7 @@ addTypeChildren(UA_Server *server, UA_Session *session,
/* Copy members of the type and supertypes (and instantiate them) */
for(size_t i = 0; i < hierarchySize; ++i) {
- retval = copyAllChildren(server, session, &hierarchy[i], &node->nodeId);
+ retval = copyAllChildren(server, session, &hierarchy[i], nodeId);
if(retval != UA_STATUSCODE_GOOD)
break;
}
@@ -39298,22 +42895,6 @@ addTypeChildren(UA_Server *server, UA_Session *session,
return retval;
}
-static UA_StatusCode
-addRef(UA_Server *server, UA_Session *session, const UA_NodeId *nodeId,
- const UA_NodeId *referenceTypeId, const UA_NodeId *parentNodeId,
- UA_Boolean forward) {
- UA_AddReferencesItem ref_item;
- UA_AddReferencesItem_init(&ref_item);
- ref_item.sourceNodeId = *nodeId;
- ref_item.referenceTypeId = *referenceTypeId;
- ref_item.isForward = forward;
- ref_item.targetNodeId.nodeId = *parentNodeId;
-
- UA_StatusCode retval = UA_STATUSCODE_GOOD;
- Operation_addReference(server, session, NULL, &ref_item, &retval);
- return retval;
-}
-
/************/
/* Add Node */
/************/
@@ -39331,15 +42912,16 @@ AddNode_addRefs(UA_Server *server, UA_Session *session, const UA_NodeId *nodeId,
return UA_STATUSCODE_BADNODEIDUNKNOWN;
/* Use the typeDefinition as parent for type-nodes */
- if(node->nodeClass == UA_NODECLASS_VARIABLETYPE ||
- node->nodeClass == UA_NODECLASS_OBJECTTYPE ||
- node->nodeClass == UA_NODECLASS_REFERENCETYPE ||
- node->nodeClass == UA_NODECLASS_DATATYPE) {
+ const UA_NodeHead *head = &node->head;
+ if(head->nodeClass == UA_NODECLASS_VARIABLETYPE ||
+ head->nodeClass == UA_NODECLASS_OBJECTTYPE ||
+ head->nodeClass == UA_NODECLASS_REFERENCETYPE ||
+ head->nodeClass == UA_NODECLASS_DATATYPE) {
if(UA_NodeId_equal(referenceTypeId, &UA_NODEID_NULL))
referenceTypeId = &hasSubtype;
const UA_Node *parentNode = UA_NODESTORE_GET(server, parentNodeId);
if(parentNode) {
- if(parentNode->nodeClass == node->nodeClass)
+ if(parentNode->head.nodeClass == head->nodeClass)
typeDefinitionId = parentNodeId;
UA_NODESTORE_RELEASE(server, parentNode);
}
@@ -39347,37 +42929,30 @@ AddNode_addRefs(UA_Server *server, UA_Session *session, const UA_NodeId *nodeId,
UA_StatusCode retval;
/* Make sure newly created node does not have itself as parent */
- if (UA_NodeId_equal(nodeId, parentNodeId)) {
- UA_LOG_NODEID_WRAP(nodeId, UA_LOG_INFO_SESSION(&server->config.logger, session,
- "AddNodes: The node %.*s can not have "
- "itself as parent",
- (int)nodeIdStr.length, nodeIdStr.data));
+ if(UA_NodeId_equal(nodeId, parentNodeId)) {
+ logAddNode(&server->config.logger, session, nodeId,
+ "A node cannot have itself as parent");
retval = UA_STATUSCODE_BADINVALIDARGUMENT;
goto cleanup;
}
/* Check parent reference. Objects may have no parent. */
- retval = checkParentReference(server, session, node->nodeClass,
- parentNodeId, referenceTypeId);
+ retval = checkParentReference(server, session, head, parentNodeId, referenceTypeId);
if(retval != UA_STATUSCODE_GOOD) {
- UA_LOG_NODEID_WRAP(nodeId, UA_LOG_INFO_SESSION(&server->config.logger, session,
- "AddNodes: The parent reference for %.*s is invalid "
- "with status code %s",
- (int)nodeIdStr.length, nodeIdStr.data,
- UA_StatusCode_name(retval)));
+ logAddNode(&server->config.logger, session, nodeId,
+ "The parent reference for is invalid");
goto cleanup;
}
/* Replace empty typeDefinition with the most permissive default */
- if((node->nodeClass == UA_NODECLASS_VARIABLE ||
- node->nodeClass == UA_NODECLASS_OBJECT) &&
+ if((head->nodeClass == UA_NODECLASS_VARIABLE ||
+ head->nodeClass == UA_NODECLASS_OBJECT) &&
UA_NodeId_isNull(typeDefinitionId)) {
- UA_LOG_NODEID_WRAP(nodeId, UA_LOG_INFO_SESSION(&server->config.logger, session,
- "AddNodes: No TypeDefinition for %.*s; Use the default "
- "TypeDefinition for the Variable/Object",
- (int)nodeIdStr.length, nodeIdStr.data));
- if(node->nodeClass == UA_NODECLASS_VARIABLE)
+ logAddNode(&server->config.logger, session, nodeId,
+ "No TypeDefinition. Use the default "
+ "TypeDefinition for the Variable/Object");
+ if(head->nodeClass == UA_NODECLASS_VARIABLE)
typeDefinitionId = &baseDataVariableType;
else
typeDefinitionId = &baseObjectType;
@@ -39389,126 +42964,100 @@ AddNode_addRefs(UA_Server *server, UA_Session *session, const UA_NodeId *nodeId,
/* Get the type node */
type = UA_NODESTORE_GET(server, typeDefinitionId);
if(!type) {
- UA_LOG_NODEID_WRAP(typeDefinitionId, UA_LOG_INFO_SESSION(&server->config.logger, session,
- "AddNodes: Node type %.*s not found",
- (int)nodeIdStr.length, nodeIdStr.data));
+ logAddNode(&server->config.logger, session, nodeId, "Node type not found");
retval = UA_STATUSCODE_BADTYPEDEFINITIONINVALID;
goto cleanup;
}
UA_Boolean typeOk = false;
- switch(node->nodeClass) {
+ const UA_NodeHead *typeHead = &type->head;
+ switch(head->nodeClass) {
case UA_NODECLASS_DATATYPE:
- typeOk = type->nodeClass == UA_NODECLASS_DATATYPE;
+ typeOk = typeHead->nodeClass == UA_NODECLASS_DATATYPE;
break;
case UA_NODECLASS_METHOD:
- typeOk = type->nodeClass == UA_NODECLASS_METHOD;
+ typeOk = typeHead->nodeClass == UA_NODECLASS_METHOD;
break;
case UA_NODECLASS_OBJECT:
- typeOk = type->nodeClass == UA_NODECLASS_OBJECTTYPE;
- break;
case UA_NODECLASS_OBJECTTYPE:
- typeOk = type->nodeClass == UA_NODECLASS_OBJECTTYPE;
+ typeOk = typeHead->nodeClass == UA_NODECLASS_OBJECTTYPE;
break;
case UA_NODECLASS_REFERENCETYPE:
- typeOk = type->nodeClass == UA_NODECLASS_REFERENCETYPE;
+ typeOk = typeHead->nodeClass == UA_NODECLASS_REFERENCETYPE;
break;
case UA_NODECLASS_VARIABLE:
- typeOk = type->nodeClass == UA_NODECLASS_VARIABLETYPE;
- break;
case UA_NODECLASS_VARIABLETYPE:
- typeOk = type->nodeClass == UA_NODECLASS_VARIABLETYPE;
+ typeOk = typeHead->nodeClass == UA_NODECLASS_VARIABLETYPE;
break;
case UA_NODECLASS_VIEW:
- typeOk = type->nodeClass == UA_NODECLASS_VIEW;
+ typeOk = typeHead->nodeClass == UA_NODECLASS_VIEW;
break;
default:
typeOk = false;
}
if(!typeOk) {
- UA_LOG_NODEID_WRAP(nodeId, UA_LOG_INFO_SESSION(&server->config.logger, session,
- "AddNodes: Type for %.*s does not match node class",
- (int)nodeIdStr.length, nodeIdStr.data));
+ logAddNode(&server->config.logger, session, nodeId,
+ "Type does not match the NodeClass");
retval = UA_STATUSCODE_BADTYPEDEFINITIONINVALID;
goto cleanup;
}
/* See if the type has the correct node class. For type-nodes, we know
* that type has the same nodeClass from checkParentReference. */
- if(node->nodeClass == UA_NODECLASS_VARIABLE) {
- if(((const UA_VariableTypeNode*)type)->isAbstract) {
- /* Get subtypes of the parent reference types */
- UA_NodeId *parentTypeHierarchy = NULL;
- size_t parentTypeHierarchySize = 0;
- retval |= referenceSubtypes(server, &parentReferences[0],
- &parentTypeHierarchySize, &parentTypeHierarchy);
- retval |= referenceSubtypes(server, &parentReferences[1],
- &parentTypeHierarchySize, &parentTypeHierarchy);
- if(retval != UA_STATUSCODE_GOOD) {
- UA_Array_delete(parentTypeHierarchy, parentTypeHierarchySize,
- &UA_TYPES[UA_TYPES_NODEID]);
- goto cleanup;
- }
-
- /* Abstract variable is allowed if parent is a children of a
- * base data variable. An abstract variable may be part of an
- * object type which again is below BaseObjectType */
- const UA_NodeId variableTypes = UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE);
- const UA_NodeId objectTypes = UA_NODEID_NUMERIC(0, UA_NS0ID_BASEOBJECTTYPE);
- if(!isNodeInTree(server, parentNodeId, &variableTypes,
- parentTypeHierarchy, parentTypeHierarchySize) &&
- !isNodeInTree(server, parentNodeId, &objectTypes,
- parentTypeHierarchy, parentTypeHierarchySize)) {
- UA_LOG_NODEID_WRAP(nodeId, UA_LOG_INFO_SESSION(&server->config.logger, session,
- "AddNodes: Type of variable node %.*s must "
- "be VariableType and not cannot be abstract",
- (int)nodeIdStr.length, nodeIdStr.data));
- retval = UA_STATUSCODE_BADTYPEDEFINITIONINVALID;
- }
- UA_Array_delete(parentTypeHierarchy, parentTypeHierarchySize,
- &UA_TYPES[UA_TYPES_NODEID]);
- if(retval != UA_STATUSCODE_GOOD)
- goto cleanup;
+ if(head->nodeClass == UA_NODECLASS_VARIABLE &&
+ type->variableTypeNode.isAbstract) {
+ /* Get subtypes of the parent reference types */
+ UA_ReferenceTypeSet refTypes1, refTypes2;
+ retval |= referenceTypeIndices(server, &parentReferences[0], &refTypes1, true);
+ retval |= referenceTypeIndices(server, &parentReferences[1], &refTypes2, true);
+ UA_ReferenceTypeSet refTypes = UA_ReferenceTypeSet_union(refTypes1, refTypes2);
+ if(retval != UA_STATUSCODE_GOOD)
+ goto cleanup;
+
+ /* Abstract variable is allowed if parent is a children of a
+ * base data variable. An abstract variable may be part of an
+ * object type which again is below BaseObjectType */
+ const UA_NodeId variableTypes = UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE);
+ const UA_NodeId objectTypes = UA_NODEID_NUMERIC(0, UA_NS0ID_BASEOBJECTTYPE);
+ if(!isNodeInTree(server, parentNodeId, &variableTypes, &refTypes) &&
+ !isNodeInTree(server, parentNodeId, &objectTypes, &refTypes)) {
+ logAddNode(&server->config.logger, session, nodeId,
+ "Type of variable node must be a "
+ "VariableType and not cannot be abstract");
+ retval = UA_STATUSCODE_BADTYPEDEFINITIONINVALID;
+ goto cleanup;
}
}
- if(node->nodeClass == UA_NODECLASS_OBJECT) {
- if(((const UA_ObjectTypeNode*)type)->isAbstract) {
- /* Get subtypes of the parent reference types */
- UA_NodeId *parentTypeHierarchy = NULL;
- size_t parentTypeHierarchySize = 0;
- retval |= referenceSubtypes(server, &parentReferences[0],
- &parentTypeHierarchySize, &parentTypeHierarchy);
- retval |= referenceSubtypes(server, &parentReferences[1],
- &parentTypeHierarchySize, &parentTypeHierarchy);
- if(retval != UA_STATUSCODE_GOOD) {
- UA_Array_delete(parentTypeHierarchy, parentTypeHierarchySize,
- &UA_TYPES[UA_TYPES_NODEID]);
- goto cleanup;
- }
+ if(head->nodeClass == UA_NODECLASS_OBJECT &&
+ type->objectTypeNode.isAbstract) {
+ /* Get subtypes of the parent reference types */
+ UA_ReferenceTypeSet refTypes1, refTypes2;
+ retval |= referenceTypeIndices(server, &parentReferences[0], &refTypes1, true);
+ retval |= referenceTypeIndices(server, &parentReferences[1], &refTypes2, true);
+ UA_ReferenceTypeSet refTypes = UA_ReferenceTypeSet_union(refTypes1, refTypes2);
+ if(retval != UA_STATUSCODE_GOOD)
+ goto cleanup;
- /* Object node created of an abstract ObjectType. Only allowed
- * if within BaseObjectType folder or if it's an event (subType of BaseEventType) */
- const UA_NodeId objectTypes = UA_NODEID_NUMERIC(0, UA_NS0ID_BASEOBJECTTYPE);
- UA_Boolean isInBaseObjectType =
- isNodeInTree(server, parentNodeId, &objectTypes,
- parentTypeHierarchy, parentTypeHierarchySize);
-
- const UA_NodeId eventTypes = UA_NODEID_NUMERIC(0, UA_NS0ID_BASEEVENTTYPE);
- UA_Boolean isInBaseEventType =
- isNodeInTree(server, &type->nodeId, &eventTypes, &hasSubtype, 1);
-
- if(!isInBaseObjectType && !(isInBaseEventType && UA_NodeId_isNull(parentNodeId))) {
- UA_LOG_NODEID_WRAP(nodeId, UA_LOG_INFO_SESSION(&server->config.logger, session,
- "AddNodes: Type of object node %.*s must "
- "be ObjectType and not be abstract",
- (int)nodeIdStr.length, nodeIdStr.data));
- retval = UA_STATUSCODE_BADTYPEDEFINITIONINVALID;
- }
- UA_Array_delete(parentTypeHierarchy, parentTypeHierarchySize,
- &UA_TYPES[UA_TYPES_NODEID]);
- if(retval != UA_STATUSCODE_GOOD)
- goto cleanup;
+
+ /* Object node created of an abstract ObjectType. Only allowed if
+ * within BaseObjectType folder or if it's an event (subType of
+ * BaseEventType) */
+ const UA_NodeId objectTypes = UA_NODEID_NUMERIC(0, UA_NS0ID_BASEOBJECTTYPE);
+ UA_Boolean isInBaseObjectType =
+ isNodeInTree(server, parentNodeId, &objectTypes, &refTypes);
+
+ const UA_NodeId eventTypes = UA_NODEID_NUMERIC(0, UA_NS0ID_BASEEVENTTYPE);
+ UA_Boolean isInBaseEventType =
+ isNodeInTree_singleRef(server, &type->head.nodeId, &eventTypes,
+ UA_REFERENCETYPEINDEX_HASSUBTYPE);
+
+ if(!isInBaseObjectType &&
+ !(isInBaseEventType && UA_NodeId_isNull(parentNodeId))) {
+ logAddNode(&server->config.logger, session, nodeId,
+ "Type of ObjectNode must be ObjectType and not be abstract");
+ retval = UA_STATUSCODE_BADTYPEDEFINITIONINVALID;
+ goto cleanup;
}
}
}
@@ -39516,33 +43065,30 @@ AddNode_addRefs(UA_Server *server, UA_Session *session, const UA_NodeId *nodeId,
/* Add reference to the parent */
if(!UA_NodeId_isNull(parentNodeId)) {
if(UA_NodeId_isNull(referenceTypeId)) {
- UA_LOG_NODEID_WRAP(nodeId, UA_LOG_INFO_SESSION(&server->config.logger, session,
- "AddNodes: Reference to parent of %.*s cannot be null",
- (int)nodeIdStr.length, nodeIdStr.data));
+ logAddNode(&server->config.logger, session, nodeId,
+ "Reference to parent cannot be null");
retval = UA_STATUSCODE_BADTYPEDEFINITIONINVALID;
goto cleanup;
}
- retval = addRef(server, session, &node->nodeId, referenceTypeId, parentNodeId, false);
+ retval = addRef(server, session, &head->nodeId, referenceTypeId,
+ parentNodeId, false);
if(retval != UA_STATUSCODE_GOOD) {
- UA_LOG_NODEID_WRAP(nodeId, UA_LOG_INFO_SESSION(&server->config.logger, session,
- "AddNodes: Adding reference to parent of %.*s failed",
- (int)nodeIdStr.length, nodeIdStr.data));
+ logAddNode(&server->config.logger, session, nodeId,
+ "Adding reference to parent failed");
goto cleanup;
}
}
/* Add a hasTypeDefinition reference */
- if(node->nodeClass == UA_NODECLASS_VARIABLE ||
- node->nodeClass == UA_NODECLASS_OBJECT) {
+ if(head->nodeClass == UA_NODECLASS_VARIABLE ||
+ head->nodeClass == UA_NODECLASS_OBJECT) {
UA_assert(type != NULL); /* see above */
- retval = addRef(server, session, &node->nodeId, &hasTypeDefinition, &type->nodeId, true);
+ retval = addRef(server, session, &head->nodeId, &hasTypeDefinition,
+ &type->head.nodeId, true);
if(retval != UA_STATUSCODE_GOOD) {
- UA_LOG_NODEID_WRAP(nodeId, UA_LOG_INFO_SESSION(&server->config.logger, session,
- "AddNodes: Adding a reference to the type "
- "definition of %.*s failed with error code %s",
- (int)nodeIdStr.length, nodeIdStr.data,
- UA_StatusCode_name(retval)));
+ logAddNode(&server->config.logger, session, nodeId,
+ "Adding a reference to the type definition failed");
}
}
@@ -39560,26 +43106,27 @@ AddNode_raw(UA_Server *server, UA_Session *session, void *nodeContext,
const UA_AddNodesItem *item, UA_NodeId *outNewNodeId) {
/* Do not check access for server */
if(session != &server->adminSession && server->config.accessControl.allowAddNode) {
- UA_UNLOCK(server->serviceMutex)
- if (!server->config.accessControl.allowAddNode(server, &server->config.accessControl,
- &session->sessionId, session->sessionHandle, item)) {
- UA_LOCK(server->serviceMutex);
+ UA_UNLOCK(&server->serviceMutex);
+ if(!server->config.accessControl.
+ allowAddNode(server, &server->config.accessControl,
+ &session->sessionId, session->sessionHandle, item)) {
+ UA_LOCK(&server->serviceMutex);
return UA_STATUSCODE_BADUSERACCESSDENIED;
}
- UA_LOCK(server->serviceMutex);
+ UA_LOCK(&server->serviceMutex);
}
/* Check the namespaceindex */
if(item->requestedNewNodeId.nodeId.namespaceIndex >= server->namespacesSize) {
UA_LOG_INFO_SESSION(&server->config.logger, session,
- "AddNodes: Namespace invalid");
+ "AddNode: Namespace invalid");
return UA_STATUSCODE_BADNODEIDINVALID;
}
if(item->nodeAttributes.encoding != UA_EXTENSIONOBJECT_DECODED &&
item->nodeAttributes.encoding != UA_EXTENSIONOBJECT_DECODED_NODELETE) {
UA_LOG_INFO_SESSION(&server->config.logger, session,
- "AddNodes: Node attributes invalid");
+ "AddNode: Node attributes invalid");
return UA_STATUSCODE_BADINTERNALERROR;
}
@@ -39587,18 +43134,20 @@ AddNode_raw(UA_Server *server, UA_Session *session, void *nodeContext,
UA_Node *node = UA_NODESTORE_NEW(server, item->nodeClass);
if(!node) {
UA_LOG_INFO_SESSION(&server->config.logger, session,
- "AddNodes: Node could not create a node "
+ "AddNode: Node could not create a node "
"in the nodestore");
return UA_STATUSCODE_BADOUTOFMEMORY;
}
+ UA_NodeId tmpOutId = UA_NODEID_NULL;
/* Fill the node attributes */
- node->context = nodeContext;
- UA_StatusCode retval = UA_NodeId_copy(&item->requestedNewNodeId.nodeId, &node->nodeId);
+ node->head.context = nodeContext;
+ UA_StatusCode retval =
+ UA_NodeId_copy(&item->requestedNewNodeId.nodeId, &node->head.nodeId);
if(retval != UA_STATUSCODE_GOOD)
goto create_error;
- retval = UA_QualifiedName_copy(&item->browseName, &node->browseName);
+ retval = UA_QualifiedName_copy(&item->browseName, &node->head.browseName);
if(retval != UA_STATUSCODE_GOOD)
goto create_error;
@@ -39608,17 +43157,25 @@ AddNode_raw(UA_Server *server, UA_Session *session, void *nodeContext,
goto create_error;
/* Add the node to the nodestore */
+ if(!outNewNodeId)
+ outNewNodeId = &tmpOutId;
retval = UA_NODESTORE_INSERT(server, node, outNewNodeId);
- if(retval != UA_STATUSCODE_GOOD)
+ if(retval != UA_STATUSCODE_GOOD) {
UA_LOG_INFO_SESSION(&server->config.logger, session,
- "AddNodes: Node could not add the new node "
+ "AddNode: Node could not add the new node "
"to the nodestore with error code %s",
UA_StatusCode_name(retval));
- return retval;
+ return retval;
+ }
+
+ if(outNewNodeId == &tmpOutId)
+ UA_NodeId_clear(&tmpOutId);
+
+ return UA_STATUSCODE_GOOD;
create_error:
UA_LOG_INFO_SESSION(&server->config.logger, session,
- "AddNodes: Node could not create a node "
+ "AddNode: Node could not create a node "
"with error code %s", UA_StatusCode_name(retval));
UA_NODESTORE_DELETE(server, node);
return retval;
@@ -39700,7 +43257,8 @@ Operation_addNode_begin(UA_Server *server, UA_Session *session, void *nodeContex
/* Set the BrowsenName before adding to the Nodestore. The BrowseName is
* immutable afterwards. */
UA_Boolean noBrowseName = UA_QualifiedName_isNull(&item->browseName);
- UA_StatusCode retval = checkSetBrowseName(server, session, (UA_AddNodesItem*)(uintptr_t)item);
+ UA_StatusCode retval =
+ checkSetBrowseName(server, session, (UA_AddNodesItem*)(uintptr_t)item);
if(retval != UA_STATUSCODE_GOOD)
return retval;
@@ -39724,75 +43282,14 @@ Operation_addNode_begin(UA_Server *server, UA_Session *session, void *nodeContex
return retval;
}
-static UA_StatusCode
-recursiveTypeCheckAddChildren(UA_Server *server, UA_Session *session,
- const UA_Node **nodeptr, const UA_Node *type) {
- UA_assert(type != NULL);
- UA_StatusCode retval = UA_STATUSCODE_GOOD;
- const UA_Node *node = *nodeptr;
-
- /* Use attributes from the type. The value and value constraints are the
- * same for the variable and variabletype attribute structs. */
- if(node->nodeClass == UA_NODECLASS_VARIABLE ||
- node->nodeClass == UA_NODECLASS_VARIABLETYPE) {
- retval = useVariableTypeAttributes(server, session, (const UA_VariableNode**)nodeptr,
- (const UA_VariableTypeNode*)type);
- node = *nodeptr; /* If the node was replaced */
- if(retval != UA_STATUSCODE_GOOD) {
- UA_LOG_NODEID_WRAP(&node->nodeId, UA_LOG_INFO_SESSION(&server->config.logger, session,
- "AddNodes: Using attributes for %.*s from the variable type "
- "failed with error code %s", (int)nodeIdStr.length,
- nodeIdStr.data, UA_StatusCode_name(retval)));
- return retval;
- }
-
- /* Check NodeClass for 'hasSubtype'. UA_NODECLASS_VARIABLE not allowed to have subtype */
- if((node->nodeClass == UA_NODECLASS_VARIABLE) && (UA_NodeId_equal(
- &node->references->referenceTypeId, &hasSubtype))) {
- UA_LOG_INFO_SESSION(&server->config.logger, session,
- "AddNodes: VariableType not allowed to have HasSubType");
- return UA_STATUSCODE_BADREFERENCENOTALLOWED;
- }
-
- /* Check if all attributes hold the constraints of the type now. The initial
- * attributes must type-check. The constructor might change the attributes
- * again. Then, the changes are type-checked by the normal write service. */
- retval = typeCheckVariableNode(server, session, (const UA_VariableNode*)node,
- (const UA_VariableTypeNode*)type);
- if(retval != UA_STATUSCODE_GOOD) {
- UA_LOG_NODEID_WRAP(&node->nodeId, UA_LOG_INFO_SESSION(&server->config.logger, session,
- "AddNodes: Type-checking the variable node %.*s "
- "failed with error code %s", (int)nodeIdStr.length,
- nodeIdStr.data, UA_StatusCode_name(retval)));
- return retval;
- }
- }
-
- /* Add (mandatory) child nodes from the type definition */
- if(node->nodeClass == UA_NODECLASS_VARIABLE ||
- node->nodeClass == UA_NODECLASS_OBJECT) {
- retval = addTypeChildren(server, session, node, type);
- if(retval != UA_STATUSCODE_GOOD) {
- UA_LOG_NODEID_WRAP(&node->nodeId, UA_LOG_INFO_SESSION(&server->config.logger, session,
- "AddNodes: Adding child nodes of %.*s failed with error code %s",
- (int)nodeIdStr.length, nodeIdStr.data, UA_StatusCode_name(retval)));
- }
- }
-
- return UA_STATUSCODE_GOOD;
-}
-
/* Construct children first */
static UA_StatusCode
recursiveCallConstructors(UA_Server *server, UA_Session *session,
- const UA_Node *node, const UA_Node *type) {
- if(node->constructed)
- return UA_STATUSCODE_GOOD;
-
- /* Construct the children */
+ const UA_NodeId *nodeId, const UA_Node *type) {
+ /* Browse the children */
UA_BrowseDescription bd;
UA_BrowseDescription_init(&bd);
- bd.nodeId = node->nodeId;
+ bd.nodeId = *nodeId;
bd.referenceTypeId = UA_NODEID_NUMERIC(0, UA_NS0ID_AGGREGATES);
bd.includeSubtypes = true;
bd.browseDirection = UA_BROWSEDIRECTION_FORWARD;
@@ -39804,30 +43301,34 @@ recursiveCallConstructors(UA_Server *server, UA_Session *session,
if(br.statusCode != UA_STATUSCODE_GOOD)
return br.statusCode;
- /* Call the constructor for every unconstructed node */
+ /* Call the constructor for every unconstructed child node */
UA_StatusCode retval = UA_STATUSCODE_GOOD;
for(size_t i = 0; i < br.referencesSize; ++i) {
UA_ReferenceDescription *rd = &br.references[i];
+ if(!UA_ExpandedNodeId_isLocal(&rd->nodeId))
+ continue;
const UA_Node *target = UA_NODESTORE_GET(server, &rd->nodeId.nodeId);
if(!target)
continue;
- if(target->constructed) {
+ if(target->head.constructed) {
UA_NODESTORE_RELEASE(server, target);
continue;
}
const UA_Node *targetType = NULL;
- if(node->nodeClass == UA_NODECLASS_VARIABLE ||
- node->nodeClass == UA_NODECLASS_OBJECT) {
- targetType = getNodeType(server, target);
+ if(target->head.nodeClass == UA_NODECLASS_VARIABLE ||
+ target->head.nodeClass == UA_NODECLASS_OBJECT) {
+ targetType = getNodeType(server, &target->head);
if(!targetType) {
UA_NODESTORE_RELEASE(server, target);
retval = UA_STATUSCODE_BADTYPEDEFINITIONINVALID;
break;
}
}
- retval = recursiveCallConstructors(server, session, target, targetType);
+
UA_NODESTORE_RELEASE(server, target);
+ retval = recursiveCallConstructors(server, session, &rd->nodeId.nodeId, targetType);
+
if(targetType)
UA_NODESTORE_RELEASE(server, targetType);
if(retval != UA_STATUSCODE_GOOD)
@@ -39840,133 +43341,307 @@ recursiveCallConstructors(UA_Server *server, UA_Session *session,
if(retval != UA_STATUSCODE_GOOD)
return retval;
- /* Get the node type constructor */
- const UA_NodeTypeLifecycle *lifecycle = NULL;
- if(type && node->nodeClass == UA_NODECLASS_OBJECT) {
- const UA_ObjectTypeNode *ot = (const UA_ObjectTypeNode*)type;
- lifecycle = &ot->lifecycle;
- } else if(type && node->nodeClass == UA_NODECLASS_VARIABLE) {
- const UA_VariableTypeNode *vt = (const UA_VariableTypeNode*)type;
- lifecycle = &vt->lifecycle;
- }
+ /* Get the node context */
+ const UA_Node *node = UA_NODESTORE_GET(server, nodeId);
+ if(!node)
+ return UA_STATUSCODE_BADNODEIDUNKNOWN;
+ void *context = node->head.context;
+ UA_NODESTORE_RELEASE(server, node);
/* Call the global constructor */
- void *context = node->context;
if(server->config.nodeLifecycle.constructor) {
- UA_UNLOCK(server->serviceMutex);
- retval = server->config.nodeLifecycle.constructor(server, &session->sessionId,
- session->sessionHandle,
- &node->nodeId, &context);
- UA_LOCK(server->serviceMutex);
+ UA_UNLOCK(&server->serviceMutex);
+ retval = server->config.nodeLifecycle.
+ constructor(server, &session->sessionId,
+ session->sessionHandle, nodeId, &context);
+ UA_LOCK(&server->serviceMutex);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
}
- /* Call the type constructor */
- if(retval == UA_STATUSCODE_GOOD && lifecycle && lifecycle->constructor) {
- UA_UNLOCK(server->serviceMutex)
+ /* Call the local (per-type) constructor */
+ const UA_NodeTypeLifecycle *lifecycle = NULL;
+ if(type && node->head.nodeClass == UA_NODECLASS_OBJECT)
+ lifecycle = &type->objectTypeNode.lifecycle;
+ else if(type && node->head.nodeClass == UA_NODECLASS_VARIABLE)
+ lifecycle = &type->variableTypeNode.lifecycle;
+ if(lifecycle && lifecycle->constructor) {
+ UA_UNLOCK(&server->serviceMutex);
retval = lifecycle->constructor(server, &session->sessionId,
- session->sessionHandle, &type->nodeId,
- type->context, &node->nodeId, &context);
- UA_LOCK(server->serviceMutex);
+ session->sessionHandle, &type->head.nodeId,
+ type->head.context, nodeId, &context);
+ UA_LOCK(&server->serviceMutex);
+ if(retval != UA_STATUSCODE_GOOD)
+ goto global_destructor;
}
- if(retval != UA_STATUSCODE_GOOD)
- goto fail1;
-
/* Set the context *and* mark the node as constructed */
- if(retval == UA_STATUSCODE_GOOD)
- retval = UA_Server_editNode(server, &server->adminSession, &node->nodeId,
- (UA_EditNodeCallback)setConstructedNodeContext,
- context);
+ retval = UA_Server_editNode(server, &server->adminSession, nodeId,
+ (UA_EditNodeCallback)setConstructedNodeContext, context);
+ if(retval != UA_STATUSCODE_GOOD)
+ goto local_destructor;
/* All good, return */
- if(retval == UA_STATUSCODE_GOOD)
- return retval;
+ return retval;
/* Fail. Call the destructors. */
+ local_destructor:
if(lifecycle && lifecycle->destructor) {
- UA_UNLOCK(server->serviceMutex);
- lifecycle->destructor(server, &session->sessionId,
- session->sessionHandle, &type->nodeId,
- type->context, &node->nodeId, &context);
- UA_LOCK(server->serviceMutex)
+ UA_UNLOCK(&server->serviceMutex);
+ lifecycle->destructor(server, &session->sessionId, session->sessionHandle,
+ &type->head.nodeId, type->head.context, nodeId, &context);
+ UA_LOCK(&server->serviceMutex);
}
-
- fail1:
+ global_destructor:
if(server->config.nodeLifecycle.destructor) {
- UA_UNLOCK(server->serviceMutex);
+ UA_UNLOCK(&server->serviceMutex);
server->config.nodeLifecycle.destructor(server, &session->sessionId,
session->sessionHandle,
- &node->nodeId, context);
- UA_LOCK(server->serviceMutex);
+ nodeId, context);
+ UA_LOCK(&server->serviceMutex);
}
-
return retval;
}
-static void
-recursiveDeconstructNode(UA_Server *server, UA_Session *session,
- size_t hierarchicalReferencesSize,
- UA_ExpandedNodeId *hierarchicalReferences,
- const UA_Node *node);
+/* Add new ReferenceType to the subtypes bitfield */
+static UA_StatusCode
+addReferenceTypeSubtype(UA_Server *server, UA_Session *session,
+ UA_Node *node, void *context) {
+ node->referenceTypeNode.subTypes =
+ UA_ReferenceTypeSet_union(node->referenceTypeNode.subTypes,
+ *(UA_ReferenceTypeSet*)context);
+ return UA_STATUSCODE_GOOD;
+}
-static void
-recursiveDeleteNode(UA_Server *server, UA_Session *session,
- size_t hierarchicalReferencesSize,
- UA_ExpandedNodeId *hierarchicalReferences,
- const UA_Node *node, UA_Boolean removeTargetRefs);
+static UA_StatusCode
+setReferenceTypeSubtypes(UA_Server *server, const UA_ReferenceTypeNode *node) {
+ /* Get the ReferenceTypes upwards in the hierarchy */
+ size_t parentsSize = 0;
+ UA_ExpandedNodeId *parents = NULL;
+ UA_ReferenceTypeSet reftypes_subtype = UA_REFTYPESET(UA_REFERENCETYPEINDEX_HASSUBTYPE);
+ UA_StatusCode res =
+ browseRecursive(server, 1, &node->head.nodeId, UA_BROWSEDIRECTION_INVERSE,
+ &reftypes_subtype, UA_NODECLASS_UNSPECIFIED,
+ false, &parentsSize, &parents);
+ if(res != UA_STATUSCODE_GOOD)
+ return res;
+
+ /* Add the ReferenceTypeIndex of this node */
+ const UA_ReferenceTypeSet *newRefSet = &node->subTypes;
+ for(size_t i = 0; i < parentsSize; i++) {
+ UA_Server_editNode(server, &server->adminSession, &parents[i].nodeId,
+ addReferenceTypeSubtype, (void*)(uintptr_t)newRefSet);
+ }
+
+ UA_Array_delete(parents, parentsSize, &UA_TYPES[UA_TYPES_EXPANDEDNODEID]);
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_StatusCode
+setVariableNodeDynamic(UA_Server *server, UA_Session *session,
+ UA_Node *node, const void *_) {
+ (void)_; /* unused */
+ if(node->head.nodeClass == UA_NODECLASS_VARIABLE)
+ ((UA_VariableNode*)node)->isDynamic = true;
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_StatusCode
+checkSetIsDynamicVariable(UA_Server *server, UA_Session *session,
+ const UA_NodeId *nodeId) {
+ /* Get all hierarchical reference types */
+ UA_ReferenceTypeSet reftypes_hierarchical;
+ UA_ReferenceTypeSet_init(&reftypes_hierarchical);
+ UA_NodeId hierarchicalRefs = UA_NODEID_NUMERIC(0, UA_NS0ID_HIERARCHICALREFERENCES);
+ UA_StatusCode res =
+ referenceTypeIndices(server, &hierarchicalRefs, &reftypes_hierarchical, true);
+ if(res != UA_STATUSCODE_GOOD)
+ return res;
+
+ /* Is the variable under the server object? */
+ UA_NodeId serverNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER);
+ if(isNodeInTree(server, nodeId, &serverNodeId, &reftypes_hierarchical))
+ return UA_STATUSCODE_GOOD;
+
+ /* Is the variable in the type hierarchy? */
+ UA_NodeId typesNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_TYPESFOLDER);
+ if(isNodeInTree(server, nodeId, &typesNodeId, &reftypes_hierarchical))
+ return UA_STATUSCODE_GOOD;
+
+ /* Is the variable a property of a method node (InputArguments /
+ * OutputArguments)? */
+ UA_BrowseDescription bd;
+ UA_BrowseDescription_init(&bd);
+ bd.nodeId = *nodeId;
+ bd.browseDirection = UA_BROWSEDIRECTION_INVERSE;
+ bd.referenceTypeId = UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY);
+ bd.includeSubtypes = false;
+ bd.nodeClassMask = UA_NODECLASS_METHOD;
+ UA_BrowseResult br;
+ UA_BrowseResult_init(&br);
+ UA_UInt32 maxrefs = 0;
+ Operation_Browse(server, session, &maxrefs, &bd, &br);
+ UA_Boolean hasParentMethod = (br.referencesSize > 0);
+ UA_BrowseResult_clear(&br);
+ if(hasParentMethod)
+ return UA_STATUSCODE_GOOD;
+
+ /* Set the variable to "dynamic" */
+ UA_Server_editNode(server, session, nodeId,
+ (UA_EditNodeCallback)setVariableNodeDynamic, NULL);
+
+ return UA_STATUSCODE_GOOD;
+}
/* Children, references, type-checking, constructors. */
UA_StatusCode
AddNode_finish(UA_Server *server, UA_Session *session, const UA_NodeId *nodeId) {
- UA_StatusCode retval = UA_STATUSCODE_GOOD;
-
/* Get the node */
+ const UA_Node *type = NULL;
const UA_Node *node = UA_NODESTORE_GET(server, nodeId);
if(!node)
return UA_STATUSCODE_BADNODEIDUNKNOWN;
- const UA_Node *type = NULL;
+ /* Set the ReferenceTypesSet of subtypes in the ReferenceTypeNode */
+ UA_StatusCode retval = UA_STATUSCODE_GOOD;
+ if(node->head.nodeClass == UA_NODECLASS_REFERENCETYPE) {
+ retval = setReferenceTypeSubtypes(server, &node->referenceTypeNode);
+ if(retval != UA_STATUSCODE_GOOD)
+ goto cleanup;
+ }
- /* Instantiate variables and objects */
- if(node->nodeClass == UA_NODECLASS_VARIABLE ||
- node->nodeClass == UA_NODECLASS_VARIABLETYPE ||
- node->nodeClass == UA_NODECLASS_OBJECT) {
- /* Get the type node */
- type = getNodeType(server, node);
+ /* Check NodeClass for 'hasSubtype'. UA_NODECLASS_VARIABLE not allowed
+ * to have subtype */
+ if(node->head.nodeClass == UA_NODECLASS_VARIABLE) {
+ for(size_t i = 0; i < node->head.referencesSize; i++) {
+ if(node->head.references[i].referenceTypeIndex ==
+ UA_REFERENCETYPEINDEX_HASSUBTYPE) {
+ UA_LOG_NODEID_INFO(&node->head.nodeId,
+ UA_LOG_INFO_SESSION(&server->config.logger, session,
+ "AddNode (%.*s): Variable not allowed "
+ "to have HasSubType reference",
+ (int)nodeIdStr.length, nodeIdStr.data));
+ retval = UA_STATUSCODE_BADREFERENCENOTALLOWED;
+ goto cleanup;
+ }
+ }
+ }
+
+ /* Get the type node */
+ if(node->head.nodeClass == UA_NODECLASS_VARIABLE ||
+ node->head.nodeClass == UA_NODECLASS_VARIABLETYPE ||
+ node->head.nodeClass == UA_NODECLASS_OBJECT) {
+ type = getNodeType(server, &node->head);
if(!type) {
if(server->bootstrapNS0)
goto constructor;
- UA_LOG_NODEID_WRAP(&node->nodeId, UA_LOG_INFO_SESSION(&server->config.logger, session,
- "AddNodes: Node type for %.*s not found",
- (int)nodeIdStr.length, nodeIdStr.data));
+ logAddNode(&server->config.logger, session, &node->head.nodeId,
+ "Node type not found");
retval = UA_STATUSCODE_BADTYPEDEFINITIONINVALID;
goto cleanup;
}
+ }
+
+ /* Initialize and typecheck the variable */
+ if(node->head.nodeClass == UA_NODECLASS_VARIABLE ||
+ node->head.nodeClass == UA_NODECLASS_VARIABLETYPE) {
+ /* Use attributes from the type. The value and value constraints are the
+ * same for the variable and variabletype attribute structs. */
+ retval = useVariableTypeAttributes(server, session,
+ &node->variableNode,
+ &type->variableTypeNode);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_LOG_NODEID_INFO(&node->head.nodeId,
+ UA_LOG_INFO_SESSION(&server->config.logger, session,
+ "AddNode (%.*s): Using attributes for from "
+ "the variable type failed with error code %s",
+ (int)nodeIdStr.length, nodeIdStr.data,
+ UA_StatusCode_name(retval)));
+ goto cleanup;
+ }
+
+ /* Get a new pointer to the node. It might have been switched out */
+#ifdef UA_ENABLE_IMMUTABLE_NODES
+ UA_NODESTORE_RELEASE(server, node);
+ node = UA_NODESTORE_GET(server, nodeId);
+ if(!node || (node->head.nodeClass != UA_NODECLASS_VARIABLE &&
+ node->head.nodeClass != UA_NODECLASS_VARIABLETYPE)) {
+ retval = UA_STATUSCODE_BADINTERNALERROR;
+ goto cleanup;
+ }
+#endif
+
+ /* Check if all attributes hold the constraints of the type now. The initial
+ * attributes must type-check. The constructor might change the attributes
+ * again. Then, the changes are type-checked by the normal write service. */
+ retval = typeCheckVariableNode(server, session, &node->variableNode,
+ &type->variableTypeNode);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_LOG_NODEID_INFO(&node->head.nodeId,
+ UA_LOG_INFO_SESSION(&server->config.logger, session,
+ "AddNode (%.*s): Type-checking "
+ "failed with error code %s", (int)nodeIdStr.length,
+ nodeIdStr.data, UA_StatusCode_name(retval)));
+ goto cleanup;
+ }
+ }
- retval = recursiveTypeCheckAddChildren(server, session, &node, type);
+ /* Add (mandatory) child nodes from the type definition */
+ if(node->head.nodeClass == UA_NODECLASS_VARIABLE ||
+ node->head.nodeClass == UA_NODECLASS_OBJECT) {
+ retval = addTypeChildren(server, session, nodeId, &type->head.nodeId);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_LOG_NODEID_INFO(&node->head.nodeId,
+ UA_LOG_INFO_SESSION(&server->config.logger, session,
+ "AddNode (%.*s): Adding child nodes "
+ "failed with error code %s", (int)nodeIdStr.length,
+ nodeIdStr.data, UA_StatusCode_name(retval)));
+ goto cleanup;
+ }
+ }
+
+ /* Add (mandatory) child nodes from the HasInterface references */
+ if(node->head.nodeClass == UA_NODECLASS_OBJECT) {
+ retval = addInterfaceChildren(server, session, nodeId, &type->head.nodeId);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_LOG_NODEID_INFO(&node->head.nodeId,
+ UA_LOG_INFO_SESSION(&server->config.logger, session,
+ "AddNode (%.*s): Adding child nodes "
+ "interface failed with error code %s",
+ (int)nodeIdStr.length, nodeIdStr.data,
+ UA_StatusCode_name(retval)));
+ goto cleanup;
+ }
+ }
+
+ /* Set variables to dynamic (source and server timestamps are meaningful) if
+ * they fulfill some conditions */
+ if(node->head.nodeClass == UA_NODECLASS_VARIABLE) {
+ retval = checkSetIsDynamicVariable(server, session, nodeId);
if(retval != UA_STATUSCODE_GOOD)
goto cleanup;
}
/* Call the constructor(s) */
constructor:
- retval = recursiveCallConstructors(server, session, node, type);
+ if(!node->head.constructed)
+ retval = recursiveCallConstructors(server, session, nodeId, type);
if(retval != UA_STATUSCODE_GOOD) {
- UA_LOG_NODEID_WRAP(&node->nodeId, UA_LOG_INFO_SESSION(&server->config.logger, session,
- "AddNodes: Calling the node constructor(s) of %.*s failed "
- "with status code %s", (int)nodeIdStr.length,
- nodeIdStr.data, UA_StatusCode_name(retval)));
+ UA_LOG_NODEID_INFO(&node->head.nodeId,
+ UA_LOG_INFO_SESSION(&server->config.logger, session,
+ "AddNode (%.*s): Calling the node constructor(s) "
+ "failed with status code %s", (int)nodeIdStr.length,
+ nodeIdStr.data, UA_StatusCode_name(retval)));
}
cleanup:
if(type)
UA_NODESTORE_RELEASE(server, type);
- if(retval != UA_STATUSCODE_GOOD) {
- recursiveDeconstructNode(server, session, 0, NULL, node);
- recursiveDeleteNode(server, session, 0, NULL, node, true);
- }
- UA_NODESTORE_RELEASE(server, node);
+ if(node)
+ UA_NODESTORE_RELEASE(server, node);
+ if(retval != UA_STATUSCODE_GOOD)
+ deleteNode(server, *nodeId, true);
return retval;
}
@@ -39974,7 +43649,8 @@ static void
Operation_addNode(UA_Server *server, UA_Session *session, void *nodeContext,
const UA_AddNodesItem *item, UA_AddNodesResult *result) {
result->statusCode =
- Operation_addNode_begin(server, session, nodeContext, item, &item->parentNodeId.nodeId,
+ Operation_addNode_begin(server, session, nodeContext,
+ item, &item->parentNodeId.nodeId,
&item->referenceTypeId, &result->addedNodeId);
if(result->statusCode != UA_STATUSCODE_GOOD)
return;
@@ -39992,7 +43668,7 @@ Service_AddNodes(UA_Server *server, UA_Session *session,
const UA_AddNodesRequest *request,
UA_AddNodesResponse *response) {
UA_LOG_DEBUG_SESSION(&server->config.logger, session, "Processing AddNodesRequest");
- UA_LOCK_ASSERT(server->serviceMutex, 1);
+ UA_LOCK_ASSERT(&server->serviceMutex, 1);
if(server->config.maxNodesPerNodeManagement != 0 &&
request->nodesToAddSize > server->config.maxNodesPerNodeManagement) {
@@ -40003,21 +43679,19 @@ Service_AddNodes(UA_Server *server, UA_Session *session,
response->responseHeader.serviceResult =
UA_Server_processServiceOperations(server, session,
(UA_ServiceOperation)Operation_addNode, NULL,
- &request->nodesToAddSize, &UA_TYPES[UA_TYPES_ADDNODESITEM],
- &response->resultsSize, &UA_TYPES[UA_TYPES_ADDNODESRESULT]);
+ &request->nodesToAddSize,
+ &UA_TYPES[UA_TYPES_ADDNODESITEM],
+ &response->resultsSize,
+ &UA_TYPES[UA_TYPES_ADDNODESRESULT]);
}
UA_StatusCode
-addNode(UA_Server *server, const UA_NodeClass nodeClass,
- const UA_NodeId *requestedNewNodeId,
- const UA_NodeId *parentNodeId,
- const UA_NodeId *referenceTypeId,
- const UA_QualifiedName browseName,
- const UA_NodeId *typeDefinition,
- const UA_NodeAttributes *attr,
- const UA_DataType *attributeType,
+addNode(UA_Server *server, const UA_NodeClass nodeClass, const UA_NodeId *requestedNewNodeId,
+ const UA_NodeId *parentNodeId, const UA_NodeId *referenceTypeId,
+ const UA_QualifiedName browseName, const UA_NodeId *typeDefinition,
+ const UA_NodeAttributes *attr, const UA_DataType *attributeType,
void *nodeContext, UA_NodeId *outNewNodeId) {
- UA_LOCK_ASSERT(server->serviceMutex, 1);
+ UA_LOCK_ASSERT(&server->serviceMutex, 1);
/* Create the AddNodesItem */
UA_AddNodesItem item;
@@ -40028,9 +43702,8 @@ addNode(UA_Server *server, const UA_NodeClass nodeClass,
item.parentNodeId.nodeId = *parentNodeId;
item.referenceTypeId = *referenceTypeId;
item.typeDefinition.nodeId = *typeDefinition;
- item.nodeAttributes.encoding = UA_EXTENSIONOBJECT_DECODED_NODELETE;
- item.nodeAttributes.content.decoded.type = attributeType;
- item.nodeAttributes.content.decoded.data = (void*)(uintptr_t)attr;
+ UA_ExtensionObject_setValueNoDelete(&item.nodeAttributes,
+ (void*)(uintptr_t)attr, attributeType);
/* Call the normal addnodes service */
UA_AddNodesResult result;
@@ -40053,44 +43726,44 @@ __UA_Server_addNode(UA_Server *server, const UA_NodeClass nodeClass,
const UA_NodeAttributes *attr,
const UA_DataType *attributeType,
void *nodeContext, UA_NodeId *outNewNodeId) {
- UA_LOCK(server->serviceMutex)
- UA_StatusCode reval = addNode(server, nodeClass, requestedNewNodeId, parentNodeId,
- referenceTypeId, browseName, typeDefinition, attr, attributeType, nodeContext, outNewNodeId);
- UA_UNLOCK(server->serviceMutex);
+ UA_LOCK(&server->serviceMutex);
+ UA_StatusCode reval =
+ addNode(server, nodeClass, requestedNewNodeId, parentNodeId,
+ referenceTypeId, browseName, typeDefinition, attr,
+ attributeType, nodeContext, outNewNodeId);
+ UA_UNLOCK(&server->serviceMutex);
return reval;
}
UA_StatusCode
UA_Server_addNode_begin(UA_Server *server, const UA_NodeClass nodeClass,
- const UA_NodeId requestedNewNodeId,
- const UA_NodeId parentNodeId,
- const UA_NodeId referenceTypeId,
- const UA_QualifiedName browseName,
- const UA_NodeId typeDefinition,
- const void *attr, const UA_DataType *attributeType,
- void *nodeContext, UA_NodeId *outNewNodeId) {
+ const UA_NodeId requestedNewNodeId, const UA_NodeId parentNodeId,
+ const UA_NodeId referenceTypeId, const UA_QualifiedName browseName,
+ const UA_NodeId typeDefinition, const void *attr,
+ const UA_DataType *attributeType, void *nodeContext,
+ UA_NodeId *outNewNodeId) {
UA_AddNodesItem item;
UA_AddNodesItem_init(&item);
item.nodeClass = nodeClass;
item.requestedNewNodeId.nodeId = requestedNewNodeId;
item.browseName = browseName;
item.typeDefinition.nodeId = typeDefinition;
- item.nodeAttributes.encoding = UA_EXTENSIONOBJECT_DECODED_NODELETE;
- item.nodeAttributes.content.decoded.type = attributeType;
- item.nodeAttributes.content.decoded.data = (void*)(uintptr_t)attr;
+ UA_ExtensionObject_setValueNoDelete(&item.nodeAttributes,
+ (void*)(uintptr_t)attr, attributeType);
- UA_LOCK(server->serviceMutex);
- UA_StatusCode retval = Operation_addNode_begin(server, &server->adminSession, nodeContext, &item,
- &parentNodeId, &referenceTypeId, outNewNodeId);
- UA_UNLOCK(server->serviceMutex);
+ UA_LOCK(&server->serviceMutex);
+ UA_StatusCode retval =
+ Operation_addNode_begin(server, &server->adminSession, nodeContext, &item,
+ &parentNodeId, &referenceTypeId, outNewNodeId);
+ UA_UNLOCK(&server->serviceMutex);
return retval;
}
UA_StatusCode
UA_Server_addNode_finish(UA_Server *server, const UA_NodeId nodeId) {
- UA_LOCK(server->serviceMutex);
+ UA_LOCK(&server->serviceMutex);
UA_StatusCode retval = AddNode_finish(server, &server->adminSession, &nodeId);
- UA_UNLOCK(server->serviceMutex);
+ UA_UNLOCK(&server->serviceMutex);
return retval;
}
@@ -40104,177 +43777,182 @@ Operation_deleteReference(UA_Server *server, UA_Session *session, void *context,
/* Remove references to this node (in the other nodes) */
static void
-removeIncomingReferences(UA_Server *server, UA_Session *session,
- const UA_Node *node) {
+removeIncomingReferences(UA_Server *server, UA_Session *session, const UA_NodeHead *head) {
UA_DeleteReferencesItem item;
UA_DeleteReferencesItem_init(&item);
- item.targetNodeId.nodeId = node->nodeId;
+ item.targetNodeId.nodeId = head->nodeId;
item.deleteBidirectional = false;
+
UA_StatusCode dummy;
- for(size_t i = 0; i < node->referencesSize; ++i) {
- UA_NodeReferenceKind *refs = &node->references[i];
- item.isForward = refs->isInverse;
- item.referenceTypeId = refs->referenceTypeId;
- for(size_t j = 0; j < refs->refTargetsSize; ++j) {
- item.sourceNodeId = refs->refTargets[j].targetId.nodeId;
+ for(size_t i = 0; i < head->referencesSize; ++i) {
+ const UA_NodeReferenceKind *rk = &head->references[i];
+ item.isForward = rk->isInverse;
+ item.referenceTypeId =
+ *UA_NODESTORE_GETREFERENCETYPEID(server, rk->referenceTypeIndex);
+ const UA_ReferenceTarget *t = NULL;
+ while((t = UA_NodeReferenceKind_iterate(rk, t))) {
+ if(!UA_NodePointer_isLocal(t->targetId))
+ continue;
+ item.sourceNodeId = UA_NodePointer_toNodeId(t->targetId);
Operation_deleteReference(server, session, NULL, &item, &dummy);
}
}
}
-/* A node can only be deleted if it has at most one incoming hierarchical
- * reference. If hierarchicalReferences is NULL, always remove. */
+/* A node is auto-deleted if all its hierarchical parents are being deleted */
static UA_Boolean
-multipleHierarchies(size_t hierarchicalRefsSize, UA_ExpandedNodeId *hierarchicalRefs,
- const UA_Node *node) {
- if(!hierarchicalRefs)
- return false;
-
- size_t incomingRefs = 0;
- for(size_t i = 0; i < node->referencesSize; i++) {
- const UA_NodeReferenceKind *k = &node->references[i];
- if(!k->isInverse)
+hasParentRef(const UA_NodeHead *head, const UA_ReferenceTypeSet *refSet,
+ RefTree *refTree) {
+ for(size_t i = 0; i < head->referencesSize; i++) {
+ const UA_NodeReferenceKind *rk = &head->references[i];
+ if(!rk->isInverse)
continue;
-
- UA_Boolean hierarchical = false;
- for(size_t j = 0; j < hierarchicalRefsSize; j++) {
- if(UA_NodeId_equal(&hierarchicalRefs[j].nodeId,
- &k->referenceTypeId)) {
- hierarchical = true;
- break;
- }
- }
- if(!hierarchical)
+ if(!UA_ReferenceTypeSet_contains(refSet, rk->referenceTypeIndex))
continue;
-
- incomingRefs += k->refTargetsSize;
- if(incomingRefs > 1)
- return true;
+ const UA_ReferenceTarget *t = NULL;
+ while((t = UA_NodeReferenceKind_iterate(rk, t))) {
+ if(!UA_NodePointer_isLocal(t->targetId))
+ continue;
+ UA_NodeId tmpId = UA_NodePointer_toNodeId(t->targetId);
+ if(!RefTree_containsNodeId(refTree, &tmpId))
+ return true;
+ }
}
-
return false;
}
-/* Recursively call the destructors of this node and all child nodes.
- * Deconstructs the parent before its children. */
static void
-recursiveDeconstructNode(UA_Server *server, UA_Session *session,
- size_t hierarchicalRefsSize,
- UA_ExpandedNodeId *hierarchicalRefs,
- const UA_Node *node) {
- /* Was the constructor called for the node? */
- if(!node->constructed)
- return;
+deconstructNodeSet(UA_Server *server, UA_Session *session,
+ UA_ReferenceTypeSet *hierarchRefsSet, RefTree *refTree) {
+ /* Deconstruct the nodes based on the RefTree entries, parent nodes first */
+ for(size_t i = 0; i < refTree->size; i++) {
+ const UA_Node *member = UA_NODESTORE_GET(server, &refTree->targets[i].nodeId);
+ if(!member)
+ continue;
- /* Call the type-level destructor */
- void *context = node->context; /* No longer needed after this function */
- if(node->nodeClass == UA_NODECLASS_OBJECT ||
- node->nodeClass == UA_NODECLASS_VARIABLE) {
- const UA_Node *type = getNodeType(server, node);
- if(type) {
- const UA_NodeTypeLifecycle *lifecycle;
- if(node->nodeClass == UA_NODECLASS_OBJECT)
- lifecycle = &((const UA_ObjectTypeNode*)type)->lifecycle;
- else
- lifecycle = &((const UA_VariableTypeNode*)type)->lifecycle;
- if(lifecycle->destructor) {
- UA_UNLOCK(server->serviceMutex);
- lifecycle->destructor(server,
- &session->sessionId, session->sessionHandle,
- &type->nodeId, type->context,
- &node->nodeId, &context);
- UA_LOCK(server->serviceMutex);
+ /* Call the type-level destructor */
+ void *context = member->head.context; /* No longer needed after this function */
+ if(member->head.nodeClass == UA_NODECLASS_OBJECT ||
+ member->head.nodeClass == UA_NODECLASS_VARIABLE) {
+ const UA_Node *type = getNodeType(server, &member->head);
+ if(type) {
+ /* Get the lifecycle */
+ const UA_NodeTypeLifecycle *lifecycle;
+ if(member->head.nodeClass == UA_NODECLASS_OBJECT)
+ lifecycle = &type->objectTypeNode.lifecycle;
+ else
+ lifecycle = &type->variableTypeNode.lifecycle;
+
+ /* Call the destructor */
+ if(lifecycle->destructor) {
+ UA_UNLOCK(&server->serviceMutex);
+ lifecycle->destructor(server,
+ &session->sessionId, session->sessionHandle,
+ &type->head.nodeId, type->head.context,
+ &member->head.nodeId, &context);
+ UA_LOCK(&server->serviceMutex);
+ }
+
+ /* Release the type node */
+ UA_NODESTORE_RELEASE(server, type);
}
- UA_NODESTORE_RELEASE(server, type);
}
- }
- /* Call the global destructor */
- if(server->config.nodeLifecycle.destructor) {
- UA_UNLOCK(server->serviceMutex);
- server->config.nodeLifecycle.destructor(server, &session->sessionId,
- session->sessionHandle,
- &node->nodeId, context);
- UA_LOCK(server->serviceMutex);
- }
+ /* Call the global destructor */
+ if(server->config.nodeLifecycle.destructor) {
+ UA_UNLOCK(&server->serviceMutex);
+ server->config.nodeLifecycle.destructor(server, &session->sessionId,
+ session->sessionHandle,
+ &member->head.nodeId, context);
+ UA_LOCK(&server->serviceMutex);
+ }
- /* Set the constructed flag to false */
- UA_Server_editNode(server, &server->adminSession, &node->nodeId,
- (UA_EditNodeCallback)setDeconstructedNode, context);
+ /* Release the node. Don't access the node context from here on. */
+ UA_NODESTORE_RELEASE(server, member);
- /* Browse to get all children of the node */
- UA_BrowseDescription bd;
- UA_BrowseDescription_init(&bd);
- bd.nodeId = node->nodeId;
- bd.referenceTypeId = UA_NODEID_NUMERIC(0, UA_NS0ID_AGGREGATES);
- bd.includeSubtypes = true;
- bd.browseDirection = UA_BROWSEDIRECTION_FORWARD;
+ /* Set the constructed flag to false */
+ UA_Server_editNode(server, &server->adminSession, &refTree->targets[i].nodeId,
+ (UA_EditNodeCallback)setDeconstructedNode, NULL);
+ }
+}
- UA_BrowseResult br;
- UA_BrowseResult_init(&br);
- UA_UInt32 maxrefs = 0;
- Operation_Browse(server, session, &maxrefs, &bd, &br);
- if(br.statusCode != UA_STATUSCODE_GOOD)
- return;
+/* The processNodeLayer function searches all children's of the head node and
+ * adds the children node to the RefTree if all incoming references sources are
+ * contained in the RefTree (No external references to this node --> node can be
+ * deleted) */
+static UA_StatusCode
+autoDeleteChildren(UA_Server *server, UA_Session *session, RefTree *refTree,
+ const UA_ReferenceTypeSet *hierarchRefsSet, const UA_NodeHead *head){
+ UA_StatusCode res = UA_STATUSCODE_GOOD;
+ for(size_t i = 0; i < head->referencesSize; ++i) {
+ /* Check if the ReferenceType is hierarchical */
+ UA_NodeReferenceKind *refs = &head->references[i];
+ if(!UA_ReferenceTypeSet_contains(hierarchRefsSet, refs->referenceTypeIndex))
+ continue;
- /* Deconstruct every child node */
- for(size_t i = 0; i < br.referencesSize; ++i) {
- UA_ReferenceDescription *rd = &br.references[i];
- const UA_Node *child = UA_NODESTORE_GET(server, &rd->nodeId.nodeId);
- if(!child)
+ /* Check if the references are forward (to a child) */
+ if(refs->isInverse)
continue;
- /* Only delete child nodes that have no other parent */
- if(!multipleHierarchies(hierarchicalRefsSize, hierarchicalRefs, child))
- recursiveDeconstructNode(server, session, hierarchicalRefsSize,
- hierarchicalRefs, child);
- UA_NODESTORE_RELEASE(server, child);
- }
- UA_BrowseResult_clear(&br);
-}
+ /* Loop over the references */
+ const UA_ReferenceTarget *t = NULL;
+ while((t = UA_NodeReferenceKind_iterate(refs, t))) {
+ /* Get the child */
+ const UA_Node *child = UA_NODESTORE_GETFROMREF(server, t->targetId);
+ if(!child)
+ continue;
-static void
-recursiveDeleteNode(UA_Server *server, UA_Session *session,
- size_t hierarchicalRefsSize,
- UA_ExpandedNodeId *hierarchicalRefs,
- const UA_Node *node, UA_Boolean removeTargetRefs) {
- /* Browse to get all children of the node */
- UA_BrowseDescription bd;
- UA_BrowseDescription_init(&bd);
- bd.nodeId = node->nodeId;
- bd.referenceTypeId = UA_NODEID_NUMERIC(0, UA_NS0ID_AGGREGATES);
- bd.includeSubtypes = true;
- bd.browseDirection = UA_BROWSEDIRECTION_FORWARD;
+ /* Only delete child nodes that have no other parent */
+ if(!hasParentRef(&child->head, hierarchRefsSet, refTree))
+ res = RefTree_addNodeId(refTree, &child->head.nodeId, NULL);
+ UA_NODESTORE_RELEASE(server, child);
+ if(res != UA_STATUSCODE_GOOD)
+ return res;
+ }
+ }
+ return UA_STATUSCODE_GOOD;
+}
- UA_BrowseResult br;
- UA_BrowseResult_init(&br);
- UA_UInt32 maxrefs = 0;
- Operation_Browse(server, session, &maxrefs, &bd, &br);
- if(br.statusCode != UA_STATUSCODE_GOOD)
- return;
+/* Build up an ordered set (tree) of all nodes that can be deleted. Step through
+ * the ordered set in order to avoid recursion. */
+static UA_StatusCode
+buildDeleteNodeSet(UA_Server *server, UA_Session *session,
+ const UA_ReferenceTypeSet *hierarchRefsSet,
+ const UA_NodeId *initial, UA_Boolean removeTargetRefs,
+ RefTree *refTree) {
+ /* Add the initial node to delete */
+ UA_StatusCode res = RefTree_addNodeId(refTree, initial, NULL);
+ if(res != UA_STATUSCODE_GOOD)
+ return res;
- /* Remove every child */
- for(size_t i = 0; i < br.referencesSize; ++i) {
- UA_ReferenceDescription *rd = &br.references[i];
- /* Check for self-reference to avoid endless loop */
- if(UA_NodeId_equal(&node->nodeId, &rd->nodeId.nodeId))
- continue;
- const UA_Node *child = UA_NODESTORE_GET(server, &rd->nodeId.nodeId);
- if(!child)
+ /* Find out which hierarchical children should also be deleted. We know
+ * there are no "external" ExpandedNodeId in the RefTree. */
+ size_t pos = 0;
+ while(pos < refTree->size) {
+ const UA_Node *member = UA_NODESTORE_GET(server, &refTree->targets[pos].nodeId);
+ pos++;
+ if(!member)
continue;
- /* Only delete child nodes that have no other parent */
- if(!multipleHierarchies(hierarchicalRefsSize, hierarchicalRefs, child))
- recursiveDeleteNode(server, session, hierarchicalRefsSize,
- hierarchicalRefs, child, true);
- UA_NODESTORE_RELEASE(server, child);
+ res |= autoDeleteChildren(server, session, refTree, hierarchRefsSet, &member->head);
+ UA_NODESTORE_RELEASE(server, member);
}
+ return res;
+}
- UA_BrowseResult_clear(&br);
-
- if(removeTargetRefs)
- removeIncomingReferences(server, session, node);
-
- UA_NODESTORE_REMOVE(server, &node->nodeId);
+static void
+deleteNodeSet(UA_Server *server, UA_Session *session,
+ const UA_ReferenceTypeSet *hierarchRefsSet,
+ UA_Boolean removeTargetRefs, RefTree *refTree) {
+ /* Delete the nodes based on the RefTree entries */
+ for(size_t i = refTree->size; i > 0; --i) {
+ const UA_Node *member = UA_NODESTORE_GET(server, &refTree->targets[i-1].nodeId);
+ if(!member)
+ continue;
+ UA_NODESTORE_RELEASE(server, member);
+ if(removeTargetRefs)
+ removeIncomingReferences(server, session, &member->head);
+ UA_NODESTORE_REMOVE(server, &member->head.nodeId);
+ }
}
static void
@@ -40282,14 +43960,15 @@ deleteNodeOperation(UA_Server *server, UA_Session *session, void *context,
const UA_DeleteNodesItem *item, UA_StatusCode *result) {
/* Do not check access for server */
if(session != &server->adminSession && server->config.accessControl.allowDeleteNode) {
- UA_UNLOCK(server->serviceMutex);
- if ( !server->config.accessControl.allowDeleteNode(server, &server->config.accessControl,
- &session->sessionId, session->sessionHandle, item)) {
- UA_LOCK(server->serviceMutex);
+ UA_UNLOCK(&server->serviceMutex);
+ if(!server->config.accessControl.
+ allowDeleteNode(server, &server->config.accessControl,
+ &session->sessionId, session->sessionHandle, item)) {
+ UA_LOCK(&server->serviceMutex);
*result = UA_STATUSCODE_BADUSERACCESSDENIED;
return;
}
- UA_LOCK(server->serviceMutex);
+ UA_LOCK(&server->serviceMutex);
}
const UA_Node *node = UA_NODESTORE_GET(server, &item->nodeId);
@@ -40298,10 +43977,11 @@ deleteNodeOperation(UA_Server *server, UA_Session *session, void *context,
return;
}
- if(UA_Node_hasSubTypeOrInstances(node)) {
- UA_LOG_INFO_SESSION(&server->config.logger, session,
- "Delete Nodes: Cannot delete a type node "
- "with active instances or subtypes");
+ if(UA_Node_hasSubTypeOrInstances(&node->head)) {
+ UA_LOG_NODEID_INFO(&node->head.nodeId,
+ UA_LOG_INFO_SESSION(&server->config.logger, session, "DeleteNode (%.*s): "
+ "Cannot delete a type node with active instances or "
+ "subtypes", (int)nodeIdStr.length, nodeIdStr.data));
UA_NODESTORE_RELEASE(server, node);
*result = UA_STATUSCODE_BADINTERNALERROR;
return;
@@ -40310,35 +43990,51 @@ deleteNodeOperation(UA_Server *server, UA_Session *session, void *context,
/* TODO: Check if the information model consistency is violated */
/* TODO: Check if the node is a mandatory child of a parent */
+ /* Relase the node. Don't access the pointer after this! */
+ UA_NODESTORE_RELEASE(server, node);
+
/* A node can be referenced with hierarchical references from several
* parents in the information model. (But not in a circular way.) The
* hierarchical references are checked to see if a node can be deleted.
* Getting the type hierarchy can fail in case of low RAM. In that case the
* nodes are always deleted. */
- UA_ExpandedNodeId *hierarchicalRefs = NULL;
- size_t hierarchicalRefsSize = 0;
+ UA_ReferenceTypeSet hierarchRefsSet;
UA_NodeId hr = UA_NODEID_NUMERIC(0, UA_NS0ID_HIERARCHICALREFERENCES);
- browseRecursive(server, 1, &hr, 1, &subtypeId, UA_BROWSEDIRECTION_FORWARD, true,
- &hierarchicalRefsSize, &hierarchicalRefs);
- if(!hierarchicalRefs) {
+ *result = referenceTypeIndices(server, &hr, &hierarchRefsSet, true);
+ if(*result != UA_STATUSCODE_GOOD)
+ return;
+
+ /* The list of childs is needed for the deconstructing and deleting phase.
+ * Within the processNodeLayer we generate a RefTree based set of childs
+ * which can be deleted beside the parent node. */
+ RefTree refTree;
+ *result = RefTree_init(&refTree);
+ if(*result != UA_STATUSCODE_GOOD)
+ return;
+ *result = buildDeleteNodeSet(server, session, &hierarchRefsSet, &item->nodeId,
+ item->deleteTargetReferences, &refTree);
+ if(*result != UA_STATUSCODE_GOOD) {
UA_LOG_WARNING_SESSION(&server->config.logger, session,
- "Delete Nodes: Cannot test for hierarchical "
- "references. Deleting the node and all child nodes.");
+ "DeleteNode: Incomplete lookup of nodes. "
+ "Still deleting what we have.");
+ /* Continue, so the RefTree is cleaned up. Return the error message
+ * anyway. */
}
- recursiveDeconstructNode(server, session, hierarchicalRefsSize, hierarchicalRefs, node);
- recursiveDeleteNode(server, session, hierarchicalRefsSize, hierarchicalRefs, node,
- item->deleteTargetReferences);
- UA_Array_delete(hierarchicalRefs, hierarchicalRefsSize, &UA_TYPES[UA_TYPES_EXPANDEDNODEID]);
-
- UA_NODESTORE_RELEASE(server, node);
+
+ /* Deconstruct, then delete, then clean up the set */
+ deconstructNodeSet(server, session, &hierarchRefsSet, &refTree);
+ deleteNodeSet(server, session, &hierarchRefsSet,
+ item->deleteTargetReferences, &refTree);
+ RefTree_clear(&refTree);
}
-void Service_DeleteNodes(UA_Server *server, UA_Session *session,
- const UA_DeleteNodesRequest *request,
- UA_DeleteNodesResponse *response) {
+void
+Service_DeleteNodes(UA_Server *server, UA_Session *session,
+ const UA_DeleteNodesRequest *request,
+ UA_DeleteNodesResponse *response) {
UA_LOG_DEBUG_SESSION(&server->config.logger, session,
"Processing DeleteNodesRequest");
- UA_LOCK_ASSERT(server->serviceMutex, 1);
+ UA_LOCK_ASSERT(&server->serviceMutex, 1);
if(server->config.maxNodesPerNodeManagement != 0 &&
request->nodesToDeleteSize > server->config.maxNodesPerNodeManagement) {
@@ -40351,22 +44047,23 @@ void Service_DeleteNodes(UA_Server *server, UA_Session *session,
(UA_ServiceOperation)deleteNodeOperation,
NULL, &request->nodesToDeleteSize,
&UA_TYPES[UA_TYPES_DELETENODESITEM],
- &response->resultsSize, &UA_TYPES[UA_TYPES_STATUSCODE]);
+ &response->resultsSize,
+ &UA_TYPES[UA_TYPES_STATUSCODE]);
}
UA_StatusCode
UA_Server_deleteNode(UA_Server *server, const UA_NodeId nodeId,
UA_Boolean deleteReferences) {
- UA_LOCK(server->serviceMutex)
+ UA_LOCK(&server->serviceMutex);
UA_StatusCode retval = deleteNode(server, nodeId, deleteReferences);
- UA_UNLOCK(server->serviceMutex);
+ UA_UNLOCK(&server->serviceMutex);
return retval;
}
UA_StatusCode
deleteNode(UA_Server *server, const UA_NodeId nodeId,
UA_Boolean deleteReferences) {
- UA_LOCK_ASSERT(server->serviceMutex, 1);
+ UA_LOCK_ASSERT(&server->serviceMutex, 1);
UA_DeleteNodesItem item;
item.deleteTargetReferences = deleteReferences;
item.nodeId = nodeId;
@@ -40380,62 +44077,96 @@ deleteNode(UA_Server *server, const UA_NodeId nodeId,
/******************/
struct AddNodeInfo {
- const UA_AddReferencesItem *item;
- UA_UInt32 browseNameHash;
+ UA_Byte refTypeIndex;
+ UA_Boolean isForward;
+ const UA_ExpandedNodeId *targetNodeId;
+ UA_UInt32 targetBrowseNameHash;
};
static UA_StatusCode
-addOneWayReference(UA_Server *server, UA_Session *session,
- UA_Node *node, const struct AddNodeInfo *info) {
- return UA_Node_addReference(node, info->item, info->browseNameHash);
+addOneWayReference(UA_Server *server, UA_Session *session, UA_Node *node,
+ const struct AddNodeInfo *info) {
+ return UA_Node_addReference(node, info->refTypeIndex, info->isForward,
+ info->targetNodeId, info->targetBrowseNameHash);
}
static UA_StatusCode
deleteOneWayReference(UA_Server *server, UA_Session *session, UA_Node *node,
const UA_DeleteReferencesItem *item) {
- return UA_Node_deleteReference(node, item);
+ const UA_Node *refType = UA_NODESTORE_GET(server, &item->referenceTypeId);
+ if(!refType)
+ return UA_STATUSCODE_BADREFERENCETYPEIDINVALID;
+ if(refType->head.nodeClass != UA_NODECLASS_REFERENCETYPE) {
+ UA_NODESTORE_RELEASE(server, refType);
+ return UA_STATUSCODE_BADREFERENCETYPEIDINVALID;
+ }
+ UA_Byte refTypeIndex = refType->referenceTypeNode.referenceTypeIndex;
+ UA_NODESTORE_RELEASE(server, refType);
+ return UA_Node_deleteReference(node, refTypeIndex, item->isForward, &item->targetNodeId);
}
static void
Operation_addReference(UA_Server *server, UA_Session *session, void *context,
const UA_AddReferencesItem *item, UA_StatusCode *retval) {
- /* Do not check access for server */
+ (void)context;
+ UA_assert(session);
+
+ /* Check access rights */
if(session != &server->adminSession && server->config.accessControl.allowAddReference) {
- UA_UNLOCK(server->serviceMutex);
+ UA_UNLOCK(&server->serviceMutex);
if (!server->config.accessControl.
allowAddReference(server, &server->config.accessControl,
&session->sessionId, session->sessionHandle, item)) {
- UA_LOCK(server->serviceMutex);
+ UA_LOCK(&server->serviceMutex);
*retval = UA_STATUSCODE_BADUSERACCESSDENIED;
return;
}
- UA_LOCK(server->serviceMutex);
+ UA_LOCK(&server->serviceMutex);
}
- /* Currently no expandednodeids are allowed */
+ /* TODO: Currently no expandednodeids are allowed */
if(item->targetServerUri.length > 0) {
*retval = UA_STATUSCODE_BADNOTIMPLEMENTED;
return;
}
- /* Get the source and target nodes */
+ /* Check the ReferenceType and get the index */
+ const UA_Node *refType = UA_NODESTORE_GET(server, &item->referenceTypeId);
+ if(!refType) {
+ *retval = UA_STATUSCODE_BADREFERENCETYPEIDINVALID;
+ return;
+ }
+ if(refType->head.nodeClass != UA_NODECLASS_REFERENCETYPE) {
+ UA_NODESTORE_RELEASE(server, refType);
+ *retval = UA_STATUSCODE_BADREFERENCETYPEIDINVALID;
+ return;
+ }
+ UA_Byte refTypeIndex = refType->referenceTypeNode.referenceTypeIndex;
+ UA_NODESTORE_RELEASE(server, refType);
+
+ /* Get the source and target node BrowseName hash */
const UA_Node *targetNode = UA_NODESTORE_GET(server, &item->targetNodeId.nodeId);
if(!targetNode) {
*retval = UA_STATUSCODE_BADTARGETNODEIDINVALID;
return;
}
+ UA_UInt32 targetNameHash = UA_QualifiedName_hash(&targetNode->head.browseName);
+ UA_NODESTORE_RELEASE(server, targetNode);
+
const UA_Node *sourceNode = UA_NODESTORE_GET(server, &item->sourceNodeId);
- if(!targetNode) {
- UA_NODESTORE_RELEASE(server, targetNode);
+ if(!sourceNode) {
*retval = UA_STATUSCODE_BADSOURCENODEIDINVALID;
return;
}
+ UA_UInt32 sourceNameHash = UA_QualifiedName_hash(&sourceNode->head.browseName);
+ UA_NODESTORE_RELEASE(server, sourceNode);
/* Compute the BrowseName hash and release the target */
struct AddNodeInfo info;
- info.item = item;
- info.browseNameHash = UA_QualifiedName_hash(&targetNode->browseName);
- UA_NODESTORE_RELEASE(server, targetNode);
+ info.refTypeIndex = refTypeIndex;
+ info.targetNodeId = &item->targetNodeId;
+ info.isForward = item->isForward;
+ info.targetBrowseNameHash = targetNameHash;
/* Add the first direction */
*retval = UA_Server_editNode(server, session, &item->sourceNodeId,
@@ -40444,54 +44175,57 @@ Operation_addReference(UA_Server *server, UA_Session *session, void *context,
if(*retval == UA_STATUSCODE_BADDUPLICATEREFERENCENOTALLOWED) {
*retval = UA_STATUSCODE_GOOD;
firstExisted = true;
- } else if(*retval != UA_STATUSCODE_GOOD) {
- UA_NODESTORE_RELEASE(server, sourceNode);
- return;
}
+ if(*retval != UA_STATUSCODE_GOOD)
+ return;
/* Add the second direction */
- UA_AddReferencesItem secondItem;
- UA_AddReferencesItem_init(&secondItem);
- secondItem.sourceNodeId = item->targetNodeId.nodeId;
- secondItem.referenceTypeId = item->referenceTypeId;
- secondItem.isForward = !item->isForward;
- secondItem.targetNodeId.nodeId = item->sourceNodeId;
- info.item = &secondItem;
- info.browseNameHash = UA_QualifiedName_hash(&sourceNode->browseName);
- /* keep default secondItem.targetNodeClass = UA_NODECLASS_UNSPECIFIED */
- *retval = UA_Server_editNode(server, session, &secondItem.sourceNodeId,
+ UA_ExpandedNodeId target2;
+ UA_ExpandedNodeId_init(&target2);
+ target2.nodeId = item->sourceNodeId;
+ info.targetNodeId = &target2;
+ info.isForward = !info.isForward;
+ info.targetBrowseNameHash = sourceNameHash;
+ *retval = UA_Server_editNode(server, session, &item->targetNodeId.nodeId,
(UA_EditNodeCallback)addOneWayReference, &info);
- UA_NODESTORE_RELEASE(server, sourceNode);
- /* remove reference if the second direction failed */
- UA_Boolean secondExisted = false;
+ /* Second direction existed already */
if(*retval == UA_STATUSCODE_BADDUPLICATEREFERENCENOTALLOWED) {
+ /* Calculate common duplicate reference not allowed result and set bad
+ * result if BOTH directions already existed */
+ if(UA_NodeId_equal(&item->sourceNodeId, &item->targetNodeId.nodeId)) {
+ *retval = UA_STATUSCODE_GOOD;
+ UA_LOG_INFO_SESSION(&server->config.logger, session, "The source node and the target node are identical. The check for duplicate references is skipped.");
+ }
+ else if(firstExisted) {
+ *retval = UA_STATUSCODE_BADDUPLICATEREFERENCENOTALLOWED;
+ return;
+ }
*retval = UA_STATUSCODE_GOOD;
- secondExisted = true;
- } else if(*retval != UA_STATUSCODE_GOOD && !firstExisted) {
+ }
+
+ /* Remove first direction if the second direction failed */
+ if(*retval != UA_STATUSCODE_GOOD && !firstExisted) {
UA_DeleteReferencesItem deleteItem;
deleteItem.sourceNodeId = item->sourceNodeId;
deleteItem.referenceTypeId = item->referenceTypeId;
deleteItem.isForward = item->isForward;
deleteItem.targetNodeId = item->targetNodeId;
deleteItem.deleteBidirectional = false;
- /* ignore returned status code */
+ /* Ignore status code */
UA_Server_editNode(server, session, &item->sourceNodeId,
(UA_EditNodeCallback)deleteOneWayReference, &deleteItem);
}
-
- /* Calculate common duplicate reference not allowed result and set bad result
- * if BOTH directions already existed */
- if(firstExisted && secondExisted)
- *retval = UA_STATUSCODE_BADDUPLICATEREFERENCENOTALLOWED;
}
-void Service_AddReferences(UA_Server *server, UA_Session *session,
- const UA_AddReferencesRequest *request,
- UA_AddReferencesResponse *response) {
+void
+Service_AddReferences(UA_Server *server, UA_Session *session,
+ const UA_AddReferencesRequest *request,
+ UA_AddReferencesResponse *response) {
UA_LOG_DEBUG_SESSION(&server->config.logger, session,
"Processing AddReferencesRequest");
- UA_LOCK_ASSERT(server->serviceMutex, 1);
+ UA_LOCK_ASSERT(&server->serviceMutex, 1);
+ UA_assert(session);
if(server->config.maxNodesPerNodeManagement != 0 &&
request->referencesToAddSize > server->config.maxNodesPerNodeManagement) {
@@ -40504,7 +44238,8 @@ void Service_AddReferences(UA_Server *server, UA_Session *session,
(UA_ServiceOperation)Operation_addReference,
NULL, &request->referencesToAddSize,
&UA_TYPES[UA_TYPES_ADDREFERENCESITEM],
- &response->resultsSize, &UA_TYPES[UA_TYPES_STATUSCODE]);
+ &response->resultsSize,
+ &UA_TYPES[UA_TYPES_STATUSCODE]);
}
UA_StatusCode
@@ -40520,9 +44255,9 @@ UA_Server_addReference(UA_Server *server, const UA_NodeId sourceId,
item.targetNodeId = targetId;
UA_StatusCode retval = UA_STATUSCODE_GOOD;
- UA_LOCK(server->serviceMutex);
+ UA_LOCK(&server->serviceMutex);
Operation_addReference(server, &server->adminSession, NULL, &item, &retval);
- UA_UNLOCK(server->serviceMutex)
+ UA_UNLOCK(&server->serviceMutex);
return retval;
}
@@ -40534,22 +44269,24 @@ static void
Operation_deleteReference(UA_Server *server, UA_Session *session, void *context,
const UA_DeleteReferencesItem *item, UA_StatusCode *retval) {
/* Do not check access for server */
- if(session != &server->adminSession && server->config.accessControl.allowDeleteReference) {
- UA_UNLOCK(server->serviceMutex);
+ if(session != &server->adminSession &&
+ server->config.accessControl.allowDeleteReference) {
+ UA_UNLOCK(&server->serviceMutex);
if (!server->config.accessControl.
allowDeleteReference(server, &server->config.accessControl,
&session->sessionId, session->sessionHandle, item)){
- UA_LOCK(server->serviceMutex);
+ UA_LOCK(&server->serviceMutex);
*retval = UA_STATUSCODE_BADUSERACCESSDENIED;
return;
}
- UA_LOCK(server->serviceMutex)
+ UA_LOCK(&server->serviceMutex);
}
// TODO: Check consistency constraints, remove the references.
*retval = UA_Server_editNode(server, session, &item->sourceNodeId,
(UA_EditNodeCallback)deleteOneWayReference,
- /* cast away const qualifier because callback uses it anyway */
+ /* cast away const qualifier because callback
+ * uses it anyway */
(UA_DeleteReferencesItem *)(uintptr_t)item);
if(*retval != UA_STATUSCODE_GOOD)
return;
@@ -40574,7 +44311,7 @@ Service_DeleteReferences(UA_Server *server, UA_Session *session,
UA_DeleteReferencesResponse *response) {
UA_LOG_DEBUG_SESSION(&server->config.logger, session,
"Processing DeleteReferencesRequest");
- UA_LOCK_ASSERT(server->serviceMutex, 1);
+ UA_LOCK_ASSERT(&server->serviceMutex, 1);
if(server->config.maxNodesPerNodeManagement != 0 &&
request->referencesToDeleteSize > server->config.maxNodesPerNodeManagement) {
@@ -40587,7 +44324,8 @@ Service_DeleteReferences(UA_Server *server, UA_Session *session,
(UA_ServiceOperation)Operation_deleteReference,
NULL, &request->referencesToDeleteSize,
&UA_TYPES[UA_TYPES_DELETEREFERENCESITEM],
- &response->resultsSize, &UA_TYPES[UA_TYPES_STATUSCODE]);
+ &response->resultsSize,
+ &UA_TYPES[UA_TYPES_STATUSCODE]);
}
UA_StatusCode
@@ -40603,9 +44341,9 @@ UA_Server_deleteReference(UA_Server *server, const UA_NodeId sourceNodeId,
item.deleteBidirectional = deleteBidirectional;
UA_StatusCode retval = UA_STATUSCODE_GOOD;
- UA_LOCK(server->serviceMutex);
+ UA_LOCK(&server->serviceMutex);
Operation_deleteReference(server, &server->adminSession, NULL, &item, &retval);
- UA_UNLOCK(server->serviceMutex);
+ UA_UNLOCK(&server->serviceMutex);
return retval;
}
@@ -40616,24 +44354,23 @@ UA_Server_deleteReference(UA_Server *server, const UA_NodeId sourceNodeId,
static UA_StatusCode
setValueCallback(UA_Server *server, UA_Session *session,
UA_VariableNode *node, const UA_ValueCallback *callback) {
- if(node->nodeClass != UA_NODECLASS_VARIABLE)
+ if(node->head.nodeClass != UA_NODECLASS_VARIABLE)
return UA_STATUSCODE_BADNODECLASSINVALID;
node->value.data.callback = *callback;
return UA_STATUSCODE_GOOD;
}
-
-
UA_StatusCode
UA_Server_setVariableNode_valueCallback(UA_Server *server,
const UA_NodeId nodeId,
const UA_ValueCallback callback) {
- UA_LOCK(server->serviceMutex);
+ UA_LOCK(&server->serviceMutex);
UA_StatusCode retval = UA_Server_editNode(server, &server->adminSession, &nodeId,
(UA_EditNodeCallback)setValueCallback,
- /* cast away const because callback uses const anyway */
+ /* cast away const because
+ * callback uses const anyway */
(UA_ValueCallback *)(uintptr_t) &callback);
- UA_UNLOCK(server->serviceMutex);
+ UA_UNLOCK(&server->serviceMutex);
return retval;
}
@@ -40643,9 +44380,12 @@ UA_Server_setVariableNode_valueCallback(UA_Server *server,
UA_StatusCode
UA_Server_addDataSourceVariableNode(UA_Server *server, const UA_NodeId requestedNewNodeId,
- const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId,
- const UA_QualifiedName browseName, const UA_NodeId typeDefinition,
- const UA_VariableAttributes attr, const UA_DataSource dataSource,
+ const UA_NodeId parentNodeId,
+ const UA_NodeId referenceTypeId,
+ const UA_QualifiedName browseName,
+ const UA_NodeId typeDefinition,
+ const UA_VariableAttributes attr,
+ const UA_DataSource dataSource,
void *nodeContext, UA_NodeId *outNewNodeId) {
UA_AddNodesItem item;
UA_AddNodesItem_init(&item);
@@ -40656,16 +44396,15 @@ UA_Server_addDataSourceVariableNode(UA_Server *server, const UA_NodeId requested
UA_ExpandedNodeId_init(&typeDefinitionId);
typeDefinitionId.nodeId = typeDefinition;
item.typeDefinition = typeDefinitionId;
- item.nodeAttributes.encoding = UA_EXTENSIONOBJECT_DECODED_NODELETE;
- item.nodeAttributes.content.decoded.data = (void*)(uintptr_t)&attr;
- item.nodeAttributes.content.decoded.type = &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES];
+ UA_ExtensionObject_setValueNoDelete(&item.nodeAttributes, (void*)(uintptr_t)&attr,
+ &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES]);
UA_NodeId newNodeId;
if(!outNewNodeId) {
newNodeId = UA_NODEID_NULL;
outNewNodeId = &newNodeId;
}
- UA_LOCK(server->serviceMutex);
+ UA_LOCK(&server->serviceMutex);
/* Create the node and add it to the nodestore */
UA_StatusCode retval = AddNode_raw(server, &server->adminSession, nodeContext,
&item, outNewNodeId);
@@ -40687,7 +44426,7 @@ UA_Server_addDataSourceVariableNode(UA_Server *server, const UA_NodeId requested
retval = AddNode_finish(server, &server->adminSession, outNewNodeId);
cleanup:
- UA_UNLOCK(server->serviceMutex);
+ UA_UNLOCK(&server->serviceMutex);
if(outNewNodeId == &newNodeId)
UA_NodeId_clear(&newNodeId);
@@ -40696,8 +44435,8 @@ UA_Server_addDataSourceVariableNode(UA_Server *server, const UA_NodeId requested
static UA_StatusCode
setDataSource(UA_Server *server, UA_Session *session,
- UA_VariableNode* node, const UA_DataSource *dataSource) {
- if(node->nodeClass != UA_NODECLASS_VARIABLE)
+ UA_VariableNode *node, const UA_DataSource *dataSource) {
+ if(node->head.nodeClass != UA_NODECLASS_VARIABLE)
return UA_STATUSCODE_BADNODECLASSINVALID;
if(node->valueSource == UA_VALUESOURCE_DATA)
UA_DataValue_clear(&node->value.data.value);
@@ -40709,7 +44448,7 @@ setDataSource(UA_Server *server, UA_Session *session,
UA_StatusCode
setVariableNode_dataSource(UA_Server *server, const UA_NodeId nodeId,
const UA_DataSource dataSource) {
- UA_LOCK_ASSERT(server->serviceMutex, 1);
+ UA_LOCK_ASSERT(&server->serviceMutex, 1);
return UA_Server_editNode(server, &server->adminSession, &nodeId,
(UA_EditNodeCallback)setDataSource,
/* casting away const because callback casts it back anyway */
@@ -40719,12 +44458,84 @@ setVariableNode_dataSource(UA_Server *server, const UA_NodeId nodeId,
UA_StatusCode
UA_Server_setVariableNode_dataSource(UA_Server *server, const UA_NodeId nodeId,
const UA_DataSource dataSource) {
- UA_LOCK(server->serviceMutex);
+ UA_LOCK(&server->serviceMutex);
UA_StatusCode retval = setVariableNode_dataSource(server, nodeId, dataSource);
- UA_UNLOCK(server->serviceMutex);
+ UA_UNLOCK(&server->serviceMutex);
return retval;
}
+/******************************/
+/* Set External Value Source */
+/******************************/
+static UA_StatusCode
+setExternalValueSource(UA_Server *server, UA_Session *session,
+ UA_VariableNode *node, const UA_ValueBackend *externalValueSource) {
+ if(node->head.nodeClass != UA_NODECLASS_VARIABLE)
+ return UA_STATUSCODE_BADNODECLASSINVALID;
+ node->valueBackend.backendType = UA_VALUEBACKENDTYPE_EXTERNAL;
+ node->valueBackend.backend.external.value =
+ externalValueSource->backend.external.value;
+ node->valueBackend.backend.external.callback.notificationRead =
+ externalValueSource->backend.external.callback.notificationRead;
+ node->valueBackend.backend.external.callback.userWrite =
+ externalValueSource->backend.external.callback.userWrite;
+ return UA_STATUSCODE_GOOD;
+}
+
+/****************************/
+/* Set Data Source Callback */
+/****************************/
+static UA_StatusCode
+setDataSourceCallback(UA_Server *server, UA_Session *session,
+ UA_VariableNode *node, const UA_DataSource *dataSource) {
+ if(node->head.nodeClass != UA_NODECLASS_VARIABLE)
+ return UA_STATUSCODE_BADNODECLASSINVALID;
+ node->valueBackend.backendType = UA_VALUEBACKENDTYPE_DATA_SOURCE_CALLBACK;
+ node->valueBackend.backend.dataSource.read = dataSource->read;
+ node->valueBackend.backend.dataSource.write = dataSource->write;
+ return UA_STATUSCODE_GOOD;
+}
+
+/**********************/
+/* Set Value Backend */
+/**********************/
+
+UA_StatusCode
+UA_Server_setVariableNode_valueBackend(UA_Server *server, const UA_NodeId nodeId,
+ const UA_ValueBackend valueBackend){
+ UA_StatusCode retval = UA_STATUSCODE_GOOD;
+ UA_LOCK(&server->serviceMutex);
+ switch(valueBackend.backendType){
+ case UA_VALUEBACKENDTYPE_NONE:
+ UA_UNLOCK(&server->serviceMutex);
+ return UA_STATUSCODE_BADCONFIGURATIONERROR;
+ case UA_VALUEBACKENDTYPE_DATA_SOURCE_CALLBACK:
+ retval = UA_Server_editNode(server, &server->adminSession, &nodeId,
+ (UA_EditNodeCallback) setDataSourceCallback,
+ (UA_DataSource *)(uintptr_t) &valueBackend.backend.dataSource);
+ break;
+ case UA_VALUEBACKENDTYPE_INTERNAL:
+ break;
+ case UA_VALUEBACKENDTYPE_EXTERNAL:
+ retval = UA_Server_editNode(server, &server->adminSession, &nodeId,
+ (UA_EditNodeCallback) setExternalValueSource,
+ /* cast away const because callback uses const anyway */
+ (UA_ValueCallback *)(uintptr_t) &valueBackend);
+ break;
+ }
+
+
+ // UA_StatusCode retval = UA_Server_editNode(server, &server->adminSession, &nodeId,
+ // (UA_EditNodeCallback)setValueCallback,
+ /* cast away const because callback uses const anyway */
+ // (UA_ValueCallback *)(uintptr_t) &callback);
+
+
+ UA_UNLOCK(&server->serviceMutex);
+ return retval;
+}
+
+
/************************************/
/* Special Handling of Method Nodes */
/************************************/
@@ -40735,11 +44546,14 @@ static const UA_NodeId hasproperty = {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_HASPRO
static const UA_NodeId propertytype = {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_PROPERTYTYPE}};
static UA_StatusCode
-UA_Server_addMethodNodeEx_finish(UA_Server *server, const UA_NodeId nodeId, UA_MethodCallback method,
- const size_t inputArgumentsSize, const UA_Argument *inputArguments,
+UA_Server_addMethodNodeEx_finish(UA_Server *server, const UA_NodeId nodeId,
+ UA_MethodCallback method,
+ const size_t inputArgumentsSize,
+ const UA_Argument *inputArguments,
const UA_NodeId inputArgumentsRequestedNewNodeId,
UA_NodeId *inputArgumentsOutNewNodeId,
- const size_t outputArgumentsSize, const UA_Argument *outputArguments,
+ const size_t outputArgumentsSize,
+ const UA_Argument *outputArguments,
const UA_NodeId outputArgumentsRequestedNewNodeId,
UA_NodeId *outputArgumentsOutNewNodeId) {
/* Browse to see which argument nodes exist */
@@ -40844,20 +44658,24 @@ error:
deleteNode(server, inputArgsId, true);
deleteNode(server, outputArgsId, true);
UA_BrowseResult_clear(&br);
-
return retval;
}
UA_StatusCode
UA_Server_addMethodNode_finish(UA_Server *server, const UA_NodeId nodeId,
UA_MethodCallback method,
- size_t inputArgumentsSize, const UA_Argument* inputArguments,
- size_t outputArgumentsSize, const UA_Argument* outputArguments) {
- UA_LOCK(server->serviceMutex)
- UA_StatusCode retval = UA_Server_addMethodNodeEx_finish(server, nodeId, method,
- inputArgumentsSize, inputArguments, UA_NODEID_NULL, NULL,
- outputArgumentsSize, outputArguments, UA_NODEID_NULL, NULL);
- UA_UNLOCK(server->serviceMutex)
+ size_t inputArgumentsSize,
+ const UA_Argument* inputArguments,
+ size_t outputArgumentsSize,
+ const UA_Argument* outputArguments) {
+ UA_LOCK(&server->serviceMutex);
+ UA_StatusCode retval =
+ UA_Server_addMethodNodeEx_finish(server, nodeId, method,
+ inputArgumentsSize, inputArguments,
+ UA_NODEID_NULL, NULL,
+ outputArgumentsSize, outputArguments,
+ UA_NODEID_NULL, NULL);
+ UA_UNLOCK(&server->serviceMutex);
return retval;
}
@@ -40879,21 +44697,19 @@ UA_Server_addMethodNodeEx(UA_Server *server, const UA_NodeId requestedNewNodeId,
item.nodeClass = UA_NODECLASS_METHOD;
item.requestedNewNodeId.nodeId = requestedNewNodeId;
item.browseName = browseName;
- item.nodeAttributes.encoding = UA_EXTENSIONOBJECT_DECODED_NODELETE;
- item.nodeAttributes.content.decoded.data = (void*)(uintptr_t)&attr;
- item.nodeAttributes.content.decoded.type = &UA_TYPES[UA_TYPES_METHODATTRIBUTES];
-
+ UA_ExtensionObject_setValueNoDelete(&item.nodeAttributes, (void*)(uintptr_t)&attr,
+ &UA_TYPES[UA_TYPES_METHODATTRIBUTES]);
UA_NodeId newId;
if(!outNewNodeId) {
UA_NodeId_init(&newId);
outNewNodeId = &newId;
}
- UA_LOCK(server->serviceMutex);
+ UA_LOCK(&server->serviceMutex);
UA_StatusCode retval = Operation_addNode_begin(server, &server->adminSession,
nodeContext, &item, &parentNodeId,
&referenceTypeId, outNewNodeId);
if(retval != UA_STATUSCODE_GOOD) {
- UA_UNLOCK(server->serviceMutex);
+ UA_UNLOCK(&server->serviceMutex);
return retval;
}
@@ -40904,7 +44720,7 @@ UA_Server_addMethodNodeEx(UA_Server *server, const UA_NodeId requestedNewNodeId,
outputArgumentsSize, outputArguments,
outputArgumentsRequestedNewNodeId,
outputArgumentsOutNewNodeId);
- UA_UNLOCK(server->serviceMutex);
+ UA_UNLOCK(&server->serviceMutex);
if(outNewNodeId == &newId)
UA_NodeId_clear(&newId);
return retval;
@@ -40912,70 +44728,93 @@ UA_Server_addMethodNodeEx(UA_Server *server, const UA_NodeId requestedNewNodeId,
static UA_StatusCode
editMethodCallback(UA_Server *server, UA_Session* session,
- UA_Node* node, void* handle) {
- if(node->nodeClass != UA_NODECLASS_METHOD)
+ UA_Node *node, UA_MethodCallback methodCallback) {
+ if(node->head.nodeClass != UA_NODECLASS_METHOD)
return UA_STATUSCODE_BADNODECLASSINVALID;
- UA_MethodNode *mnode = (UA_MethodNode*) node;
- mnode->method = (UA_MethodCallback)(uintptr_t)handle;
+ node->methodNode.method = methodCallback;
return UA_STATUSCODE_GOOD;
}
-UA_StatusCode
+static UA_StatusCode
setMethodNode_callback(UA_Server *server,
- const UA_NodeId methodNodeId,
- UA_MethodCallback methodCallback) {
- UA_LOCK_ASSERT(server->serviceMutex, 1);
+ const UA_NodeId methodNodeId,
+ UA_MethodCallback methodCallback) {
+ UA_LOCK_ASSERT(&server->serviceMutex, 1);
return UA_Server_editNode(server, &server->adminSession, &methodNodeId,
- (UA_EditNodeCallback)editMethodCallback,
- (void*)(uintptr_t)methodCallback);
+ (UA_EditNodeCallback)editMethodCallback,
+ (void*)(uintptr_t)methodCallback);
}
UA_StatusCode
-UA_Server_setMethodNode_callback(UA_Server *server,
- const UA_NodeId methodNodeId,
- UA_MethodCallback methodCallback) {
- UA_LOCK(server->serviceMutex);
+UA_Server_setMethodNodeCallback(UA_Server *server,
+ const UA_NodeId methodNodeId,
+ UA_MethodCallback methodCallback) {
+ UA_LOCK(&server->serviceMutex);
UA_StatusCode retVal = setMethodNode_callback(server, methodNodeId, methodCallback);
- UA_UNLOCK(server->serviceMutex);
+ UA_UNLOCK(&server->serviceMutex);
return retVal;
}
+UA_StatusCode
+UA_Server_getMethodNodeCallback(UA_Server *server,
+ const UA_NodeId methodNodeId,
+ UA_MethodCallback *outMethodCallback) {
+ UA_LOCK(&server->serviceMutex);
+ const UA_Node *node = UA_NODESTORE_GET(server, &methodNodeId);
+ if(!node) {
+ UA_UNLOCK(&server->serviceMutex);
+ return UA_STATUSCODE_BADNODEIDUNKNOWN;
+ }
+
+ if(node->head.nodeClass != UA_NODECLASS_METHOD) {
+ UA_NODESTORE_RELEASE(server, node);
+ UA_UNLOCK(&server->serviceMutex);
+ return UA_STATUSCODE_BADNODECLASSINVALID;
+ }
+
+ *outMethodCallback = node->methodNode.method;
+ UA_NODESTORE_RELEASE(server, node);
+ UA_UNLOCK(&server->serviceMutex);
+ return UA_STATUSCODE_GOOD;
+}
+
#endif
/************************/
/* Lifecycle Management */
/************************/
+void UA_EXPORT
+UA_Server_setAdminSessionContext(UA_Server *server,
+ void *context) {
+ server->adminSession.sessionHandle = context;
+}
+
static UA_StatusCode
setNodeTypeLifecycle(UA_Server *server, UA_Session *session,
- UA_Node* node, UA_NodeTypeLifecycle *lifecycle) {
- if(node->nodeClass == UA_NODECLASS_OBJECTTYPE) {
- UA_ObjectTypeNode *ot = (UA_ObjectTypeNode*)node;
- ot->lifecycle = *lifecycle;
- return UA_STATUSCODE_GOOD;
- }
-
- if(node->nodeClass == UA_NODECLASS_VARIABLETYPE) {
- UA_VariableTypeNode *vt = (UA_VariableTypeNode*)node;
- vt->lifecycle = *lifecycle;
- return UA_STATUSCODE_GOOD;
+ UA_Node *node, UA_NodeTypeLifecycle *lifecycle) {
+ if(node->head.nodeClass == UA_NODECLASS_OBJECTTYPE) {
+ node->objectTypeNode.lifecycle = *lifecycle;
+ } else if(node->head.nodeClass == UA_NODECLASS_VARIABLETYPE) {
+ node->variableTypeNode.lifecycle = *lifecycle;
+ } else {
+ return UA_STATUSCODE_BADNODECLASSINVALID;
}
-
- return UA_STATUSCODE_BADNODECLASSINVALID;
+ return UA_STATUSCODE_GOOD;
}
UA_StatusCode
UA_Server_setNodeTypeLifecycle(UA_Server *server, UA_NodeId nodeId,
UA_NodeTypeLifecycle lifecycle) {
- UA_LOCK(server->serviceMutex);
+ UA_LOCK(&server->serviceMutex);
UA_StatusCode retval = UA_Server_editNode(server, &server->adminSession, &nodeId,
(UA_EditNodeCallback)setNodeTypeLifecycle,
&lifecycle);
- UA_UNLOCK(server->serviceMutex);
+ UA_UNLOCK(&server->serviceMutex);
return retval;
}
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/src/server/ua_services_discovery_multicast.c" ***********************************/
+/**** amalgamated original file "/src/server/ua_services_discovery_multicast.c" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -40989,7 +44828,7 @@ UA_Server_setNodeTypeLifecycle(UA_Server *server, UA_NodeId nodeId,
#if defined(UA_ENABLE_DISCOVERY) && defined(UA_ENABLE_DISCOVERY_MULTICAST)
-#if UA_MULTITHREADING >= 200
+#if UA_MULTITHREADING >= 100
static void *
multicastWorkerLoop(UA_Server *server) {
@@ -41068,8 +44907,8 @@ addMdnsRecordForNetworkLayer(UA_Server *server, const UA_String *appName,
retval = UA_Discovery_addRecord(server, appName, &hostname, port,
&path, UA_DISCOVERY_TCP, true,
- server->config.discovery.mdns.serverCapabilities,
- server->config.discovery.mdns.serverCapabilitiesSize,
+ server->config.mdnsConfig.serverCapabilities,
+ server->config.mdnsConfig.serverCapabilitiesSize,
true);
if(retval != UA_STATUSCODE_GOOD) {
UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_NETWORK,
@@ -41081,14 +44920,14 @@ addMdnsRecordForNetworkLayer(UA_Server *server, const UA_String *appName,
}
void startMulticastDiscoveryServer(UA_Server *server) {
- UA_String *appName = &server->config.discovery.mdns.mdnsServerName;
+ UA_String *appName = &server->config.mdnsConfig.mdnsServerName;
for(size_t i = 0; i < server->config.networkLayersSize; i++)
addMdnsRecordForNetworkLayer(server, appName, &server->config.networkLayers[i]);
/* find any other server on the net */
UA_Discovery_multicastQuery(server);
-#if UA_MULTITHREADING >= 200
+#if UA_MULTITHREADING >= 100
multicastListenStart(server);
# endif
}
@@ -41110,12 +44949,12 @@ stopMulticastDiscoveryServer(UA_Server *server) {
if (retval != UA_STATUSCODE_GOOD)
continue;
- UA_Discovery_removeRecord(server, &server->config.discovery.mdns.mdnsServerName,
+ UA_Discovery_removeRecord(server, &server->config.mdnsConfig.mdnsServerName,
&hostname, port, true);
}
-#if UA_MULTITHREADING >= 200
+#if UA_MULTITHREADING >= 100
multicastListenStop(server);
# else
// send out last package with TTL = 0
@@ -41123,28 +44962,37 @@ stopMulticastDiscoveryServer(UA_Server *server) {
# endif
}
-/* All filter criteria must be fulfilled */
+/* All filter criteria must be fulfilled in the list entry. The comparison is case
+ * insensitive.
+ * @returns true if the entry matches the filter. False if the filter does not match.
+ * */
static UA_Boolean
-filterServerRecord(size_t serverCapabilityFilterSize, UA_String *serverCapabilityFilter,
+entryMatchesCapabilityFilter(size_t serverCapabilityFilterSize, UA_String *serverCapabilityFilter,
serverOnNetwork_list_entry* current) {
- // if the element has no capabilities defined, but the filter expects some, then do not use this entry
- if (serverCapabilityFilterSize > 0 && current->serverOnNetwork.serverCapabilitiesSize == 0)
- return false;
+ // if the entry has less capabilities defined than the filter, there's no match
+ if (serverCapabilityFilterSize > current->serverOnNetwork.serverCapabilitiesSize)
+ return UA_FALSE;
for(size_t i = 0; i < serverCapabilityFilterSize; i++) {
- for(size_t j = 0; j < current->serverOnNetwork.serverCapabilitiesSize; j++)
- if(!UA_String_equal(&serverCapabilityFilter[i],
- &current->serverOnNetwork.serverCapabilities[j]))
- return false;
+ UA_Boolean capabilityFound = UA_FALSE;
+ for(size_t j = 0; j < current->serverOnNetwork.serverCapabilitiesSize; j++) {
+ if(UA_String_equal_ignorecase(&serverCapabilityFilter[i],
+ &current->serverOnNetwork.serverCapabilities[j])) {
+ capabilityFound = UA_TRUE;
+ break;
+ }
+ }
+ if (!capabilityFound)
+ return UA_FALSE; // entry does not match capability
}
- return true;
+ return UA_TRUE;
}
void Service_FindServersOnNetwork(UA_Server *server, UA_Session *session,
const UA_FindServersOnNetworkRequest *request,
UA_FindServersOnNetworkResponse *response) {
- UA_LOCK_ASSERT(server->serviceMutex, 1);
+ UA_LOCK_ASSERT(&server->serviceMutex, 1);
- if (!server->config.discovery.mdnsEnable) {
+ if (!server->config.mdnsEnabled) {
response->responseHeader.serviceResult = UA_STATUSCODE_BADNOTIMPLEMENTED;
return;
}
@@ -41174,7 +45022,7 @@ void Service_FindServersOnNetwork(UA_Server *server, UA_Session *session,
break;
if(current->serverOnNetwork.recordId < request->startingRecordId)
continue;
- if(!filterServerRecord(request->serverCapabilityFilterSize,
+ if(!entryMatchesCapabilityFilter(request->serverCapabilityFilterSize,
request->serverCapabilityFilter, current))
continue;
filtered[filteredCount++] = &current->serverOnNetwork;
@@ -41246,10 +45094,10 @@ void
UA_Server_setServerOnNetworkCallback(UA_Server *server,
UA_Server_serverOnNetworkCallback cb,
void* data) {
- UA_LOCK(server->serviceMutex);
+ UA_LOCK(&server->serviceMutex);
server->discoveryManager.serverOnNetworkCallback = cb;
server->discoveryManager.serverOnNetworkCallbackData = data;
- UA_UNLOCK(server->serviceMutex);
+ UA_UNLOCK(&server->serviceMutex);
}
static void
@@ -41579,7 +45427,7 @@ iterateMulticastDiscoveryServer(UA_Server* server, UA_DateTime *nextRepeat,
#endif /* defined(UA_ENABLE_DISCOVERY) && defined(UA_ENABLE_DISCOVERY_MULTICAST) */
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/src/client/ua_client.c" ***********************************/
+/**** amalgamated original file "/src/client/ua_client.c" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -41598,6 +45446,7 @@ iterateMulticastDiscoveryServer(UA_Server* server, UA_DateTime *nextRepeat,
* Copyright 2016 (c) Lykurg
* Copyright 2017 (c) Mark Giraud, Fraunhofer IOSB
* Copyright 2018 (c) Kalycito Infotech Private Limited
+ * Copyright 2020 (c) Christian von Arnim, ISW University of Stuttgart
*/
@@ -41628,14 +45477,14 @@ UA_Client_newWithConfig(const UA_ClientConfig *config) {
}
static void
-UA_ClientConfig_deleteMembers(UA_ClientConfig *config) {
- UA_ApplicationDescription_deleteMembers(&config->clientDescription);
+UA_ClientConfig_clear(UA_ClientConfig *config) {
+ UA_ApplicationDescription_clear(&config->clientDescription);
- UA_ExtensionObject_deleteMembers(&config->userIdentityToken);
- UA_String_deleteMembers(&config->securityPolicyUri);
+ UA_ExtensionObject_clear(&config->userIdentityToken);
+ UA_String_clear(&config->securityPolicyUri);
- UA_EndpointDescription_deleteMembers(&config->endpoint);
- UA_UserTokenPolicy_deleteMembers(&config->userTokenPolicy);
+ UA_EndpointDescription_clear(&config->endpoint);
+ UA_UserTokenPolicy_clear(&config->userTokenPolicy);
if(config->certificateVerification.clear)
config->certificateVerification.clear(&config->certificateVerification);
@@ -41653,10 +45502,16 @@ UA_ClientConfig_deleteMembers(UA_ClientConfig *config) {
config->logger.clear(config->logger.context);
config->logger.log = NULL;
config->logger.clear = NULL;
+
+ if (config->sessionLocaleIdsSize > 0 && config->sessionLocaleIds) {
+ UA_Array_delete(config->sessionLocaleIds, config->sessionLocaleIdsSize, &UA_TYPES[UA_TYPES_LOCALEID]);
+ }
+ config->sessionLocaleIds = NULL;
+ config->sessionLocaleIdsSize = 0;
}
static void
-UA_Client_deleteMembers(UA_Client *client) {
+UA_Client_clear(UA_Client *client) {
/* Delete the async service calls with BADHSUTDOWN */
UA_Client_AsyncService_removeAll(client, UA_STATUSCODE_BADSHUTDOWN);
@@ -41672,13 +45527,13 @@ UA_Client_deleteMembers(UA_Client *client) {
#endif
/* Delete the timed work */
- UA_Timer_deleteMembers(&client->timer);
+ UA_Timer_clear(&client->timer);
}
void
UA_Client_delete(UA_Client* client) {
- UA_Client_deleteMembers(client);
- UA_ClientConfig_deleteMembers(&client->config);
+ UA_Client_clear(client);
+ UA_ClientConfig_clear(&client->config);
UA_free(client);
}
@@ -41701,9 +45556,9 @@ UA_Client_getConfig(UA_Client *client) {
}
#if UA_LOGLEVEL <= 300
-static const char *channelStateTexts[8] = {
- "Closed", "HELSent", "HELReceived", "ACKSent",
- "AckReceived", "OPNSent", "Open", "Closing"};
+static const char *channelStateTexts[9] = {
+ "Fresh", "HELSent", "HELReceived", "ACKSent",
+ "AckReceived", "OPNSent", "Open", "Closing", "Closed"};
static const char *sessionStateTexts[6] =
{"Closed", "CreateRequested", "Created",
"ActivateRequested", "Activated", "Closing"};
@@ -41769,7 +45624,9 @@ static UA_StatusCode
sendSymmetricServiceRequest(UA_Client *client, const void *request,
const UA_DataType *requestType, UA_UInt32 *requestId) {
/* Renew SecureChannel if necessary */
- renewSecureChannel(client);
+ UA_Client_renewSecureChannel(client);
+ if(client->connectStatus != UA_STATUSCODE_GOOD)
+ return client->connectStatus;
/* Adjusting the request header. The const attribute is violated, but we
* only touch the following members: */
@@ -41786,8 +45643,8 @@ sendSymmetricServiceRequest(UA_Client *client, const void *request,
(unsigned)rqId, requestType->typeName);
#else
UA_LOG_DEBUG_CHANNEL(&client->config.logger, &client->channel,
- "Sending request with RequestId %u of type %" PRIi16,
- (unsigned)rqId, requestType->binaryEncodingId);
+ "Sending request with RequestId %u of type %" PRIu32,
+ (unsigned)rqId, requestType->binaryEncodingId.identifier.numeric);
#endif
/* Send the message */
@@ -41828,9 +45685,8 @@ processAsyncResponse(UA_Client *client, UA_UInt32 requestId, const UA_NodeId *re
/* Verify the type of the response */
UA_Response response;
const UA_DataType *responseType = ac->responseType;
- const UA_NodeId expectedNodeId = UA_NODEID_NUMERIC(0, ac->responseType->binaryEncodingId);
UA_StatusCode retval = UA_STATUSCODE_GOOD;
- if(!UA_NodeId_equal(responseTypeId, &expectedNodeId)) {
+ if(!UA_NodeId_equal(responseTypeId, &ac->responseType->binaryEncodingId)) {
UA_init(&response, ac->responseType);
if(UA_NodeId_equal(responseTypeId, &serviceFaultId)) {
/* Decode as a ServiceFault, i.e. only the response header */
@@ -41847,14 +45703,14 @@ processAsyncResponse(UA_Client *client, UA_UInt32 requestId, const UA_NodeId *re
}
/* Decode the response */
- retval = UA_decodeBinary(responseMessage, offset, &response, responseType,
- client->config.customDataTypes);
+ retval = UA_decodeBinaryInternal(responseMessage, offset, &response, responseType,
+ client->config.customDataTypes);
process:
if(retval != UA_STATUSCODE_GOOD) {
UA_LOG_INFO(&client->config.logger, UA_LOGCATEGORY_CLIENT,
"Could not decode the response with id %u due to %s",
- requestId, UA_StatusCode_name(retval));
+ (unsigned)requestId, UA_StatusCode_name(retval));
response.responseHeader.serviceResult = retval;
} else if(response.responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
/* Decode as a ServiceFault, i.e. only the response header */
@@ -41876,7 +45732,7 @@ processAsyncResponse(UA_Client *client, UA_UInt32 requestId, const UA_NodeId *re
/* Processes the received service response. Either with an async callback or by
* decoding the message and returning it "upwards" in the
* SyncResponseDescription. */
-static void
+static UA_StatusCode
processServiceResponse(void *application, UA_SecureChannel *channel,
UA_MessageType messageType, UA_UInt32 requestId,
UA_ByteString *message) {
@@ -41886,25 +45742,22 @@ processServiceResponse(void *application, UA_SecureChannel *channel,
switch(messageType) {
case UA_MESSAGETYPE_ACK:
processACKResponse(rd->client, message);
- return;
+ return UA_STATUSCODE_GOOD;
case UA_MESSAGETYPE_OPN:
processOPNResponse(rd->client, message);
- return;
+ return UA_STATUSCODE_GOOD;
case UA_MESSAGETYPE_ERR:
processERRResponse(rd->client, message);
- return;
+ return UA_STATUSCODE_GOOD;
case UA_MESSAGETYPE_MSG:
/* Continue below */
break;
default:
UA_LOG_TRACE_CHANNEL(&rd->client->config.logger, channel, "Invalid message type");
channel->state = UA_SECURECHANNELSTATE_CLOSING;
- return;
+ return UA_STATUSCODE_BADTCPMESSAGETYPEINVALID;
}
- /* Forward declaration for the goto */
- UA_NodeId expectedNodeId = UA_NODEID_NULL;
-
/* Decode the data type identifier of the response */
size_t offset = 0;
UA_NodeId responseId;
@@ -41923,13 +45776,12 @@ processServiceResponse(void *application, UA_SecureChannel *channel,
rd->received = true;
/* Check that the response type matches */
- expectedNodeId = UA_NODEID_NUMERIC(0, rd->responseType->binaryEncodingId);
- if(!UA_NodeId_equal(&responseId, &expectedNodeId)) {
+ if(!UA_NodeId_equal(&responseId, &rd->responseType->binaryEncodingId)) {
if(UA_NodeId_equal(&responseId, &serviceFaultId)) {
UA_init(rd->response, rd->responseType);
- retval = UA_decodeBinary(message, &offset, rd->response,
- &UA_TYPES[UA_TYPES_SERVICEFAULT],
- rd->client->config.customDataTypes);
+ retval = UA_decodeBinaryInternal(message, &offset, rd->response,
+ &UA_TYPES[UA_TYPES_SERVICEFAULT],
+ rd->client->config.customDataTypes);
if(retval != UA_STATUSCODE_GOOD)
((UA_ResponseHeader*)rd->response)->serviceResult = retval;
UA_LOG_INFO(&rd->client->config.logger, UA_LOGCATEGORY_CLIENT,
@@ -41953,11 +45805,11 @@ processServiceResponse(void *application, UA_SecureChannel *channel,
#endif
/* Decode the response */
- retval = UA_decodeBinary(message, &offset, rd->response, rd->responseType,
- rd->client->config.customDataTypes);
+ retval = UA_decodeBinaryInternal(message, &offset, rd->response, rd->responseType,
+ rd->client->config.customDataTypes);
finish:
- UA_NodeId_deleteMembers(&responseId);
+ UA_NodeId_clear(&responseId);
if(retval != UA_STATUSCODE_GOOD) {
if(retval == UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED)
retval = UA_STATUSCODE_BADRESPONSETOOLARGE;
@@ -41970,13 +45822,15 @@ finish:
respHeader->serviceResult = retval;
}
}
+
+ return retval;
}
/* Receive and process messages until a synchronous message arrives or the
* timout finishes */
static UA_StatusCode
receiveResponse(UA_Client *client, void *response, const UA_DataType *responseType,
- UA_UInt32 timeout, const UA_UInt32 *synchronousRequestId) {
+ UA_DateTime maxDate, const UA_UInt32 *synchronousRequestId) {
/* Prepare the response and the structure we give into processServiceResponse */
SyncResponseDescription rd = { client, false, 0, response, responseType };
@@ -41985,13 +45839,12 @@ receiveResponse(UA_Client *client, void *response, const UA_DataType *responseTy
if(synchronousRequestId)
rd.requestId = *synchronousRequestId;
- UA_DateTime now = UA_DateTime_nowMonotonic();
- UA_DateTime maxDate = now + ((UA_DateTime)timeout * UA_DATETIME_MSEC);
UA_StatusCode retval = UA_STATUSCODE_GOOD;
+ UA_DateTime now = UA_DateTime_nowMonotonic();
do {
- if(maxDate < now)
- return UA_STATUSCODE_GOODNONCRITICALTIMEOUT;
UA_UInt32 timeout2 = (UA_UInt32)((maxDate - now) / UA_DATETIME_MSEC);
+ if(maxDate < now)
+ timeout2 = 0;
retval = UA_SecureChannel_receive(&client->channel, &rd, processServiceResponse, timeout2);
if(retval == UA_STATUSCODE_GOODNONCRITICALTIMEOUT)
break;
@@ -42005,6 +45858,8 @@ receiveResponse(UA_Client *client, void *response, const UA_DataType *responseTy
break;
}
now = UA_DateTime_nowMonotonic();
+ if(maxDate < now)
+ break;
} while(!rd.received && responseType); /* Return if we don't wait for an async response */
return retval;
@@ -42012,7 +45867,8 @@ receiveResponse(UA_Client *client, void *response, const UA_DataType *responseTy
UA_StatusCode
receiveResponseAsync(UA_Client *client, UA_UInt32 timeout) {
- UA_StatusCode res = receiveResponse(client, NULL, NULL, timeout, NULL);
+ UA_DateTime maxDate = UA_DateTime_nowMonotonic() + ((UA_DateTime)timeout * UA_DATETIME_MSEC);
+ UA_StatusCode res = receiveResponse(client, NULL, NULL, maxDate, NULL);
return (res != UA_STATUSCODE_GOODNONCRITICALTIMEOUT) ? res : UA_STATUSCODE_GOOD;
}
@@ -42038,7 +45894,8 @@ __UA_Client_Service(UA_Client *client, const void *request,
UA_ResponseHeader *respHeader = (UA_ResponseHeader*)response;
if(retval == UA_STATUSCODE_GOOD) {
/* Retrieve the response */
- retval = receiveResponse(client, response, responseType, client->config.timeout, &requestId);
+ UA_DateTime maxDate = UA_DateTime_nowMonotonic() + ((UA_DateTime)client->config.timeout * UA_DATETIME_MSEC);
+ retval = receiveResponse(client, response, responseType, maxDate, &requestId);
} else if(retval == UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED) {
respHeader->serviceResult = UA_STATUSCODE_BADREQUESTTOOLARGE;
return;
@@ -42083,6 +45940,20 @@ void UA_Client_AsyncService_removeAll(UA_Client *client, UA_StatusCode statusCod
}
}
+UA_StatusCode UA_Client_modifyAsyncCallback(UA_Client *client, UA_UInt32 requestId,
+ void *userdata, UA_ClientAsyncServiceCallback callback) {
+ AsyncServiceCall *ac;
+ LIST_FOREACH(ac, &client->asyncServiceCalls, pointers) {
+ if(ac->requestId == requestId) {
+ ac->callback = callback;
+ ac->userdata = userdata;
+ return UA_STATUSCODE_GOOD;
+ }
+ }
+
+ return UA_STATUSCODE_BADNOTFOUND;
+}
+
UA_StatusCode
__UA_Client_AsyncServiceEx(UA_Client *client, const void *request,
const UA_DataType *requestType,
@@ -42093,7 +45964,7 @@ __UA_Client_AsyncServiceEx(UA_Client *client, const void *request,
if(client->channel.state != UA_SECURECHANNELSTATE_OPEN) {
UA_LOG_INFO(&client->config.logger, UA_LOGCATEGORY_CLIENT,
"SecureChannel must be connected before sending requests");
- return UA_STATUSCODE_BADSERVERNOTCONNECTED;
+ return UA_STATUSCODE_BADSERVERNOTCONNECTED;
}
/* Prepare the entry for the linked list */
@@ -42156,13 +46027,14 @@ UA_StatusCode
UA_Client_addRepeatedCallback(UA_Client *client, UA_ClientCallback callback,
void *data, UA_Double interval_ms, UA_UInt64 *callbackId) {
return UA_Timer_addRepeatedCallback(&client->timer, (UA_ApplicationCallback)callback,
- client, data, interval_ms, callbackId);
+ client, data, interval_ms, NULL,
+ UA_TIMER_HANDLE_CYCLEMISS_WITH_CURRENTTIME, callbackId);
}
UA_StatusCode
UA_Client_changeRepeatedCallbackInterval(UA_Client *client, UA_UInt64 callbackId,
UA_Double interval_ms) {
- return UA_Timer_changeRepeatedCallbackInterval(&client->timer, callbackId, interval_ms);
+ return UA_Timer_changeRepeatedCallback(&client->timer, callbackId, interval_ms, NULL, UA_TIMER_HANDLE_CYCLEMISS_WITH_CURRENTTIME);
}
void
@@ -42237,8 +46109,11 @@ UA_StatusCode
UA_Client_run_iterate(UA_Client *client, UA_UInt32 timeout) {
/* Process timed (repeated) jobs */
UA_DateTime now = UA_DateTime_nowMonotonic();
- UA_Timer_process(&client->timer, now,
- (UA_TimerExecutionCallback)clientExecuteRepeatedCallback, client);
+ UA_DateTime maxDate =
+ UA_Timer_process(&client->timer, now, (UA_TimerExecutionCallback)
+ clientExecuteRepeatedCallback, client);
+ if(maxDate > now + ((UA_DateTime)timeout * UA_DATETIME_MSEC))
+ maxDate = now + ((UA_DateTime)timeout * UA_DATETIME_MSEC);
/* Make sure we have an open channel */
UA_StatusCode retval = UA_STATUSCODE_GOOD;
@@ -42250,7 +46125,9 @@ UA_Client_run_iterate(UA_Client *client, UA_UInt32 timeout) {
}
/* Renew Secure Channel */
- renewSecureChannel(client);
+ UA_Client_renewSecureChannel(client);
+ if(client->connectStatus != UA_STATUSCODE_GOOD)
+ return client->connectStatus;
/* Feed the server PublishRequests for the Subscriptions */
#ifdef UA_ENABLE_SUBSCRIPTIONS
@@ -42261,7 +46138,7 @@ UA_Client_run_iterate(UA_Client *client, UA_UInt32 timeout) {
UA_Client_backgroundConnectivity(client);
/* Listen on the network for the given timeout */
- retval = receiveResponse(client, NULL, NULL, timeout, NULL);
+ retval = receiveResponse(client, NULL, NULL, maxDate, NULL);
if(retval == UA_STATUSCODE_GOODNONCRITICALTIMEOUT)
retval = UA_STATUSCODE_GOOD;
if(retval != UA_STATUSCODE_GOOD) {
@@ -42284,7 +46161,12 @@ UA_Client_run_iterate(UA_Client *client, UA_UInt32 timeout) {
return client->connectStatus;
}
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/src/client/ua_client_connect.c" ***********************************/
+const UA_DataType *
+UA_Client_findDataType(UA_Client *client, const UA_NodeId *typeId) {
+ return UA_findDataTypeWithCustom(typeId, client->config.customDataTypes);
+}
+
+/**** amalgamated original file "/src/client/ua_client_connect.c" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -42314,13 +46196,13 @@ getSecurityPolicy(UA_Client *client, UA_String policyUri) {
static UA_Boolean
endpointUnconfigured(UA_Client *client) {
- UA_Byte test = 0;
- UA_Byte *pos = (UA_Byte*)&client->config.endpoint;
+ char test = 0;
+ char *pos = (char *)&client->config.endpoint;
for(size_t i = 0; i < sizeof(UA_EndpointDescription); i++)
- test = test | pos[i];
- pos = (UA_Byte*)&client->config.userTokenPolicy;
+ test = test | *(pos + i);
+ pos = (char *)&client->config.userTokenPolicy;
for(size_t i = 0; i < sizeof(UA_UserTokenPolicy); i++)
- test = test | pos[i];
+ test = test | *(pos + i);
return (test == 0);
}
@@ -42339,7 +46221,7 @@ signActivateSessionRequest(UA_Client *client, UA_SecureChannel *channel,
/* Prepare the signature */
size_t signatureSize = sp->certificateSigningAlgorithm.
- getLocalSignatureSize(sp, channel->channelContext);
+ getLocalSignatureSize(channel->channelContext);
UA_StatusCode retval = UA_String_copy(&sp->certificateSigningAlgorithm.uri,
&sd->algorithm);
if(retval != UA_STATUSCODE_GOOD)
@@ -42364,7 +46246,7 @@ signActivateSessionRequest(UA_Client *client, UA_SecureChannel *channel,
channel->remoteCertificate.length);
memcpy(dataToSign.data + channel->remoteCertificate.length,
client->remoteNonce.data, client->remoteNonce.length);
- retval = sp->certificateSigningAlgorithm.sign(sp, channel->channelContext,
+ retval = sp->certificateSigningAlgorithm.sign(channel->channelContext,
&dataToSign, &sd->signature);
/* Clean up */
@@ -42415,19 +46297,19 @@ encryptUserIdentityToken(UA_Client *client, const UA_String *userTokenSecurityPo
/* Compute the encrypted length (at least one byte padding) */
size_t plainTextBlockSize = sp->asymmetricModule.cryptoModule.
- encryptionAlgorithm.getRemotePlainTextBlockSize(sp, channelContext);
+ encryptionAlgorithm.getRemotePlainTextBlockSize(channelContext);
+ size_t encryptedBlockSize = sp->asymmetricModule.cryptoModule.
+ encryptionAlgorithm.getRemoteBlockSize(channelContext);
UA_UInt32 length = (UA_UInt32)(tokenData->length + client->remoteNonce.length);
UA_UInt32 totalLength = length + 4; /* Including the length field */
size_t blocks = totalLength / plainTextBlockSize;
- if(totalLength % plainTextBlockSize != 0)
+ if(totalLength % plainTextBlockSize != 0)
blocks++;
- size_t overHead =
- UA_SecurityPolicy_getRemoteAsymEncryptionBufferLengthOverhead(sp, channelContext,
- blocks * plainTextBlockSize);
+ size_t encryptedLength = blocks * encryptedBlockSize;
/* Allocate memory for encryption overhead */
UA_ByteString encrypted;
- retval = UA_ByteString_allocBuffer(&encrypted, (blocks * plainTextBlockSize) + overHead);
+ retval = UA_ByteString_allocBuffer(&encrypted, encryptedLength);
if(retval != UA_STATUSCODE_GOOD) {
sp->channelModule.deleteContext(channelContext);
return UA_STATUSCODE_BADOUTOFMEMORY;
@@ -42435,9 +46317,10 @@ encryptUserIdentityToken(UA_Client *client, const UA_String *userTokenSecurityPo
UA_Byte *pos = encrypted.data;
const UA_Byte *end = &encrypted.data[encrypted.length];
- UA_UInt32_encodeBinary(&length, &pos, end);
+ retval = UA_UInt32_encodeBinary(&length, &pos, end);
memcpy(pos, tokenData->data, tokenData->length);
memcpy(&pos[tokenData->length], client->remoteNonce.data, client->remoteNonce.length);
+ UA_assert(retval == UA_STATUSCODE_GOOD);
/* Add padding
*
@@ -42451,8 +46334,8 @@ encryptUserIdentityToken(UA_Client *client, const UA_String *userTokenSecurityPo
encrypted.length = paddedLength;
retval = sp->asymmetricModule.cryptoModule.encryptionAlgorithm.
- encrypt(sp, channelContext, &encrypted);
- encrypted.length = (blocks * plainTextBlockSize) + overHead;
+ encrypt(channelContext, &encrypted);
+ encrypted.length = encryptedLength;
if(iit) {
retval |= UA_String_copy(&sp->asymmetricModule.cryptoModule.encryptionAlgorithm.uri,
@@ -42496,7 +46379,7 @@ checkCreateSessionSignature(UA_Client *client, const UA_SecureChannel *channel,
memcpy(dataToVerify.data + lc->length,
client->localNonce.data, client->localNonce.length);
- retval = sp->certificateSigningAlgorithm.verify(sp, channel->channelContext, &dataToVerify,
+ retval = sp->certificateSigningAlgorithm.verify(channel->channelContext, &dataToVerify,
&response->serverSignature.signature);
UA_ByteString_clear(&dataToVerify);
return retval;
@@ -42512,9 +46395,11 @@ void
processERRResponse(UA_Client *client, const UA_ByteString *chunk) {
client->channel.state = UA_SECURECHANNELSTATE_CLOSING;
- size_t offset = 8; /* TODO: Make a define for the magic number */
+ size_t offset = 0;
UA_TcpErrorMessage errMessage;
- UA_StatusCode res = UA_TcpErrorMessage_decodeBinary(chunk, &offset, &errMessage);
+ UA_StatusCode res =
+ UA_decodeBinaryInternal(chunk, &offset, &errMessage,
+ &UA_TRANSPORT[UA_TRANSPORT_TCPERRORMESSAGE], NULL);
if(res != UA_STATUSCODE_GOOD) {
UA_LOG_ERROR_CHANNEL(&client->config.logger, &client->channel,
"Received an ERR response that could not be decoded with StatusCode %s",
@@ -42543,9 +46428,11 @@ processACKResponse(UA_Client *client, const UA_ByteString *chunk) {
UA_LOG_DEBUG(&client->config.logger, UA_LOGCATEGORY_NETWORK, "Received ACK message");
/* Decode the message */
- size_t offset = 8;
+ size_t offset = 0;
UA_TcpAcknowledgeMessage ackMessage;
- client->connectStatus = UA_TcpAcknowledgeMessage_decodeBinary(chunk, &offset, &ackMessage);
+ client->connectStatus =
+ UA_decodeBinaryInternal(chunk, &offset, &ackMessage,
+ &UA_TRANSPORT[UA_TRANSPORT_TCPACKNOWLEDGEMESSAGE], NULL);
if(client->connectStatus != UA_STATUSCODE_GOOD) {
UA_LOG_INFO(&client->config.logger, UA_LOGCATEGORY_NETWORK,
"Decoding ACK message failed");
@@ -42586,14 +46473,18 @@ sendHELMessage(UA_Client *client) {
UA_Byte *bufPos = &message.data[8]; /* skip the header */
const UA_Byte *bufEnd = &message.data[message.length];
- client->connectStatus = UA_TcpHelloMessage_encodeBinary(&hello, &bufPos, bufEnd);
+ client->connectStatus =
+ UA_encodeBinaryInternal(&hello, &UA_TRANSPORT[UA_TRANSPORT_TCPHELLOMESSAGE],
+ &bufPos, &bufEnd, NULL, NULL);
/* Encode the message header at offset 0 */
UA_TcpMessageHeader messageHeader;
messageHeader.messageTypeAndChunkType = UA_CHUNKTYPE_FINAL + UA_MESSAGETYPE_HEL;
messageHeader.messageSize = (UA_UInt32) ((uintptr_t)bufPos - (uintptr_t)message.data);
bufPos = message.data;
- retval = UA_TcpMessageHeader_encodeBinary(&messageHeader, &bufPos, bufEnd);
+ retval = UA_encodeBinaryInternal(&messageHeader,
+ &UA_TRANSPORT[UA_TRANSPORT_TCPMESSAGEHEADER],
+ &bufPos, &bufEnd, NULL, NULL);
if(retval != UA_STATUSCODE_GOOD) {
conn->releaseSendBuffer(conn, &message);
return retval;
@@ -42611,9 +46502,10 @@ sendHELMessage(UA_Client *client) {
return retval;
}
-static void
-processOPNResponseDecoded(UA_Client *client, const UA_ByteString *message, size_t offset) {
+void
+processOPNResponse(UA_Client *client, const UA_ByteString *message) {
/* Is the content of the expected type? */
+ size_t offset = 0;
UA_NodeId responseId;
UA_NodeId expectedId =
UA_NODEID_NUMERIC(0, UA_NS0ID_OPENSECURECHANNELRESPONSE_ENCODING_DEFAULTBINARY);
@@ -42631,7 +46523,8 @@ processOPNResponseDecoded(UA_Client *client, const UA_ByteString *message, size_
/* Decode the response */
UA_OpenSecureChannelResponse response;
- retval = UA_OpenSecureChannelResponse_decodeBinary(message, &offset, &response);
+ retval = UA_decodeBinaryInternal(message, &offset, &response,
+ &UA_TYPES[UA_TYPES_OPENSECURECHANNELRESPONSE], NULL);
if(retval != UA_STATUSCODE_GOOD) {
closeSecureChannel(client);
return;
@@ -42675,90 +46568,20 @@ processOPNResponseDecoded(UA_Client *client, const UA_ByteString *message, size_
return;
}
+ UA_Float lifetime = (UA_Float)response.securityToken.revisedLifetime / 1000;
UA_Boolean renew = (client->channel.state == UA_SECURECHANNELSTATE_OPEN);
- if(renew)
- UA_LOG_INFO_CHANNEL(&client->config.logger, &client->channel, "SecureChannel renewed");
- else
+ if(renew) {
+ UA_LOG_INFO_CHANNEL(&client->config.logger, &client->channel, "SecureChannel "
+ "renewed with a revised lifetime of %.2fs", lifetime);
+ } else {
UA_LOG_INFO_CHANNEL(&client->config.logger, &client->channel,
- "Opened SecureChannel with SecurityPolicy %.*s",
+ "SecureChannel opened with SecurityPolicy %.*s "
+ "and a revised lifetime of %.2fs",
(int)client->channel.securityPolicy->policyUri.length,
- client->channel.securityPolicy->policyUri.data);
-
- client->channel.state = UA_SECURECHANNELSTATE_OPEN;
-}
-
-void
-processOPNResponse(UA_Client *client, UA_ByteString *chunk) {
- UA_SecureChannel *channel = &client->channel;
- if(channel->state != UA_SECURECHANNELSTATE_OPN_SENT &&
- channel->state != UA_SECURECHANNELSTATE_OPEN) {
- UA_LOG_ERROR_CHANNEL(&client->config.logger, channel,
- "Received an unexpected OPN response");
- channel->state = UA_SECURECHANNELSTATE_CLOSING;
- return;
- }
-
- /* Skip the first header. We know length and message type. */
- size_t offset = UA_SECURE_CONVERSATION_MESSAGE_HEADER_LENGTH;
-
- /* Decode the asymmetric algorithm security header and call the callback
- * to perform checks. */
- UA_AsymmetricAlgorithmSecurityHeader asymHeader;
- UA_AsymmetricAlgorithmSecurityHeader_init(&asymHeader);
- UA_StatusCode retval =
- UA_AsymmetricAlgorithmSecurityHeader_decodeBinary(chunk, &offset, &asymHeader);
- if(retval != UA_STATUSCODE_GOOD) {
- UA_LOG_WARNING_CHANNEL(&client->config.logger, channel,
- "Could not decode the OPN header");
- closeSecureChannel(client);
- return;
- }
-
- /* Verify the certificate before creating the SecureChannel with it */
- if(asymHeader.senderCertificate.length > 0) {
- retval = client->config.certificateVerification.
- verifyCertificate(client->config.certificateVerification.context,
- &asymHeader.senderCertificate);
- if(retval != UA_STATUSCODE_GOOD) {
- UA_LOG_WARNING_CHANNEL(&client->config.logger, channel,
- "Could not verify the server's certificate");
- closeSecureChannel(client);
- return;
- }
- }
-
- retval = checkAsymHeader(channel, &asymHeader);
- UA_AsymmetricAlgorithmSecurityHeader_clear(&asymHeader);
- if(retval != UA_STATUSCODE_GOOD) {
- UA_LOG_WARNING_CHANNEL(&client->config.logger, channel,
- "Could not verify the OPN header");
- closeSecureChannel(client);
- return;
- }
-
- retval = decryptAndVerifyChunk(channel, &channel->securityPolicy->asymmetricModule.cryptoModule,
- UA_MESSAGETYPE_OPN, chunk, offset);
- if(retval != UA_STATUSCODE_GOOD) {
- UA_LOG_WARNING_CHANNEL(&client->config.logger, channel,
- "Could not decrypt and verify the OPN payload");
- closeSecureChannel(client);
- return;
- }
-
- /* Decode and verify the sequence header */
- UA_SequenceHeader sequenceHeader;
- retval = UA_SequenceHeader_decodeBinary(chunk, &offset, &sequenceHeader);
-#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
- retval |= processSequenceNumberAsym(channel, sequenceHeader.sequenceNumber);
-#endif
- if(retval != UA_STATUSCODE_GOOD) {
- UA_LOG_WARNING_CHANNEL(&client->config.logger, channel,
- "Could not process the OPN sequence number");
- closeSecureChannel(client);
- return;
+ client->channel.securityPolicy->policyUri.data, lifetime);
}
- processOPNResponseDecoded(client, chunk, offset);
+ client->channel.state = UA_SECURECHANNELSTATE_OPEN;
}
/* OPN messges to renew the channel are sent asynchronous */
@@ -42817,14 +46640,15 @@ sendOPNAsync(UA_Client *client, UA_Boolean renew) {
return UA_STATUSCODE_GOOD;
}
-void
-renewSecureChannel(UA_Client *client) {
+UA_StatusCode
+UA_Client_renewSecureChannel(UA_Client *client) {
/* Check if OPN has been sent or the SecureChannel is still valid */
if(client->channel.state != UA_SECURECHANNELSTATE_OPEN ||
client->channel.renewState == UA_SECURECHANNELRENEWSTATE_SENT ||
client->nextChannelRenewal > UA_DateTime_nowMonotonic())
- return;
+ return UA_STATUSCODE_GOODCALLAGAIN;
sendOPNAsync(client, true);
+ return client->connectStatus;
}
static void
@@ -42850,6 +46674,11 @@ responseActivateSession(UA_Client *client, void *userdata, UA_UInt32 requestId,
return;
}
+ /* Replace the nonce */
+ UA_ByteString_clear(&client->remoteNonce);
+ client->remoteNonce = activateResponse->serverNonce;
+ UA_ByteString_init(&activateResponse->serverNonce);
+
client->sessionState = UA_SESSIONSTATE_ACTIVATED;
notifyClientState(client);
}
@@ -42866,6 +46695,15 @@ activateSessionAsync(UA_Client *client) {
if(retval != UA_STATUSCODE_GOOD)
return retval;
+ if (client->config.sessionLocaleIdsSize && client->config.sessionLocaleIds) {
+ retval = UA_Array_copy(client->config.sessionLocaleIds, client->config.sessionLocaleIdsSize,
+ (void **)&request.localeIds, &UA_TYPES[UA_TYPES_LOCALEID]);
+ if (retval != UA_STATUSCODE_GOOD)
+ return retval;
+
+ request.localeIdsSize = client->config.sessionLocaleIdsSize;
+ }
+
/* If not token is set, use anonymous */
if(request.userIdentityToken.encoding == UA_EXTENSIONOBJECT_ENCODED_NOBODY) {
UA_AnonymousIdentityToken *t = UA_AnonymousIdentityToken_new();
@@ -42897,8 +46735,15 @@ activateSessionAsync(UA_Client *client) {
&UA_TYPES[UA_TYPES_ACTIVATESESSIONREQUEST],
(UA_ClientAsyncServiceCallback) responseActivateSession,
&UA_TYPES[UA_TYPES_ACTIVATESESSIONRESPONSE], NULL, NULL);
+
UA_ActivateSessionRequest_clear(&request);
- client->sessionState = UA_SESSIONSTATE_ACTIVATE_REQUESTED;
+ if(retval == UA_STATUSCODE_GOOD)
+ client->sessionState = UA_SESSIONSTATE_ACTIVATE_REQUESTED;
+ else
+ UA_LOG_ERROR(&client->config.logger, UA_LOGCATEGORY_CLIENT,
+ "ActivateSession failed when sending the request with error code %s",
+ UA_StatusCode_name(retval));
+
return retval;
}
@@ -43038,8 +46883,8 @@ responseGetEndpoints(UA_Client *client, void *userdata, UA_UInt32 requestId,
/* Log the selected endpoint */
UA_LOG_INFO(&client->config.logger, UA_LOGCATEGORY_CLIENT,
- "Selected Endpoint %.*s with SecurityMode %s and SecurityPolicy %.*s",
- (int)endpoint->endpointUrl.length, endpoint->endpointUrl.data,
+ "Selected endpoint %lu in URL %.*s with SecurityMode %s and SecurityPolicy %.*s",
+ (long unsigned)i, (int)endpoint->endpointUrl.length, endpoint->endpointUrl.data,
securityModeNames[endpoint->securityMode - 1],
(int)endpoint->securityPolicyUri.length,
endpoint->securityPolicyUri.data);
@@ -43092,13 +46937,17 @@ requestGetEndpoints(UA_Client *client) {
request.requestHeader.timestamp = UA_DateTime_now();
request.requestHeader.timeoutHint = 10000;
request.endpointUrl = client->endpointUrl;
- client->connectStatus =
+ UA_StatusCode retval =
UA_Client_sendAsyncRequest(client, &request, &UA_TYPES[UA_TYPES_GETENDPOINTSREQUEST],
(UA_ClientAsyncServiceCallback) responseGetEndpoints,
&UA_TYPES[UA_TYPES_GETENDPOINTSRESPONSE], NULL, NULL);
- if(client->connectStatus == UA_STATUSCODE_GOOD)
+ if(retval == UA_STATUSCODE_GOOD)
client->endpointsHandshake = true;
- return client->connectStatus;
+ else
+ UA_LOG_ERROR(&client->config.logger, UA_LOGCATEGORY_CLIENT,
+ "RequestGetEndpoints failed when sending the request with error code %s",
+ UA_StatusCode_name(retval));
+ return retval;
}
static void
@@ -43157,7 +47006,8 @@ createSessionAsync(UA_Client *client) {
return retval;
}
retval = client->channel.securityPolicy->symmetricModule.
- generateNonce(client->channel.securityPolicy, &client->localNonce);
+ generateNonce(client->channel.securityPolicy->policyContext,
+ &client->localNonce);
if(retval != UA_STATUSCODE_GOOD)
return retval;
}
@@ -43187,11 +47037,17 @@ createSessionAsync(UA_Client *client) {
if(retval == UA_STATUSCODE_GOOD)
client->sessionState = UA_SESSIONSTATE_CREATE_REQUESTED;
+ else
+ UA_LOG_ERROR(&client->config.logger, UA_LOGCATEGORY_CLIENT,
+ "CreateSession failed when sending the request with error code %s",
+ UA_StatusCode_name(retval));
- client->connectStatus = retval;
- return client->connectStatus;
+ return retval;
}
+static UA_StatusCode
+initConnect(UA_Client *client);
+
UA_StatusCode
connectIterate(UA_Client *client, UA_UInt32 timeout) {
UA_LOG_TRACE(&client->config.logger, UA_LOGCATEGORY_CLIENT,
@@ -43211,18 +47067,16 @@ connectIterate(UA_Client *client, UA_UInt32 timeout) {
return UA_STATUSCODE_BADCONNECTIONCLOSED;
}
- /* TCP connection */
- if(client->connection.state == UA_CONNECTIONSTATE_CLOSED) {
- /* Reopen a new TCP connection */
- client->connection =
- client->config.initConnectionFunc(client->config.localConnectionConfig,
- client->endpointUrl, client->config.timeout,
- &client->config.logger);
- return client->connectStatus;
- } else if(client->connection.state == UA_CONNECTIONSTATE_OPENING) {
- /* Poll the connection status */
+ /* The connection is closed. Reset the SecureChannel and open a new TCP
+ * connection */
+ if(client->connection.state == UA_CONNECTIONSTATE_CLOSED)
+ return initConnect(client);
+
+ /* Poll the connection status */
+ if(client->connection.state == UA_CONNECTIONSTATE_OPENING) {
client->connectStatus =
- client->config.pollConnectionFunc(client, &client->connection, timeout);
+ client->config.pollConnectionFunc(&client->connection, timeout,
+ &client->config.logger);
return client->connectStatus;
}
@@ -43257,7 +47111,7 @@ connectIterate(UA_Client *client, UA_UInt32 timeout) {
/* Open the SecureChannel */
switch(client->channel.state) {
- case UA_SECURECHANNELSTATE_CLOSED:
+ case UA_SECURECHANNELSTATE_FRESH:
client->connectStatus = sendHELMessage(client);
if(client->connectStatus == UA_STATUSCODE_GOOD) {
client->channel.state = UA_SECURECHANNELSTATE_HEL_SENT;
@@ -43285,11 +47139,11 @@ connectIterate(UA_Client *client, UA_UInt32 timeout) {
switch(client->sessionState) {
case UA_SESSIONSTATE_CLOSED:
if(!endpointUnconfigured(client)) {
- createSessionAsync(client);
+ client->connectStatus = createSessionAsync(client);
return client->connectStatus;
}
if(!client->endpointsHandshake) {
- requestGetEndpoints(client);
+ client->connectStatus = requestGetEndpoints(client);
return client->connectStatus;
}
receiveResponseAsync(client, timeout);
@@ -43299,7 +47153,7 @@ connectIterate(UA_Client *client, UA_UInt32 timeout) {
receiveResponseAsync(client, timeout);
return client->connectStatus;
case UA_SESSIONSTATE_CREATED:
- activateSessionAsync(client);
+ client->connectStatus = activateSessionAsync(client);
return client->connectStatus;
default:
break;
@@ -43331,7 +47185,14 @@ verifyClientApplicationURI(const UA_Client *client) {
}
static UA_StatusCode
-initConnect(UA_Client *client, const char *endpointUrl) {
+client_configure_securechannel(void *application, UA_SecureChannel *channel,
+ const UA_AsymmetricAlgorithmSecurityHeader *asymHeader) {
+ // TODO: Verify if certificate is the same as configured in the client endpoint config
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_StatusCode
+initConnect(UA_Client *client) {
if(client->connection.state > UA_CONNECTIONSTATE_CLOSED) {
UA_LOG_WARNING(&client->config.logger, UA_LOGCATEGORY_CLIENT,
"Client already connected");
@@ -43354,10 +47215,8 @@ initConnect(UA_Client *client, const char *endpointUrl) {
/* Initialize the SecureChannel */
UA_SecureChannel_init(&client->channel, &client->config.localConnectionConfig);
-
- /* Set the endpoint URL the client connects to */
- UA_String_clear(&client->endpointUrl);
- client->endpointUrl = UA_STRING_ALLOC(endpointUrl);
+ client->channel.certificateVerification = &client->config.certificateVerification;
+ client->channel.processOPNHeader = client_configure_securechannel;
if(client->connection.free)
client->connection.free(&client->connection);
@@ -43380,22 +47239,36 @@ initConnect(UA_Client *client, const char *endpointUrl) {
UA_StatusCode
UA_Client_connectAsync(UA_Client *client, const char *endpointUrl) {
+ /* Set the endpoint URL the client connects to */
+ UA_String_clear(&client->endpointUrl);
+ client->endpointUrl = UA_STRING_ALLOC(endpointUrl);
+
+ /* Open a Session when possible */
client->noSession = false;
- return initConnect(client, endpointUrl);
+
+ /* Connect Async */
+ return initConnect(client);
}
UA_StatusCode
UA_Client_connectSecureChannelAsync(UA_Client *client, const char *endpointUrl) {
+ /* Set the endpoint URL the client connects to */
+ UA_String_clear(&client->endpointUrl);
+ client->endpointUrl = UA_STRING_ALLOC(endpointUrl);
+
+ /* Don't open a Session */
client->noSession = true;
- return initConnect(client, endpointUrl);
+
+ /* Connect Async */
+ return initConnect(client);
}
static UA_StatusCode
-connectSync(UA_Client *client, const char *endpointUrl) {
+connectSync(UA_Client *client) {
UA_DateTime now = UA_DateTime_nowMonotonic();
UA_DateTime maxDate = now + ((UA_DateTime)client->config.timeout * UA_DATETIME_MSEC);
- UA_StatusCode retval = initConnect(client, endpointUrl);
+ UA_StatusCode retval = initConnect(client);
if(retval != UA_STATUSCODE_GOOD)
return retval;
@@ -43407,7 +47280,8 @@ connectSync(UA_Client *client, const char *endpointUrl) {
now = UA_DateTime_nowMonotonic();
if(maxDate < now)
return UA_STATUSCODE_BADTIMEOUT;
- retval = UA_Client_run_iterate(client, (UA_UInt32)((maxDate - now) / UA_DATETIME_MSEC));
+ retval = UA_Client_run_iterate(client,
+ (UA_UInt32)((maxDate - now) / UA_DATETIME_MSEC));
}
return retval;
@@ -43415,14 +47289,28 @@ connectSync(UA_Client *client, const char *endpointUrl) {
UA_StatusCode
UA_Client_connect(UA_Client *client, const char *endpointUrl) {
+ /* Set the endpoint URL the client connects to */
+ UA_String_clear(&client->endpointUrl);
+ client->endpointUrl = UA_STRING_ALLOC(endpointUrl);
+
+ /* Open a Session when possible */
client->noSession = false;
- return connectSync(client, endpointUrl);
+
+ /* Connect Synchronous */
+ return connectSync(client);
}
UA_StatusCode
UA_Client_connectSecureChannel(UA_Client *client, const char *endpointUrl) {
+ /* Set the endpoint URL the client connects to */
+ UA_String_clear(&client->endpointUrl);
+ client->endpointUrl = UA_STRING_ALLOC(endpointUrl);
+
+ /* Don't open a Session */
client->noSession = true;
- return connectSync(client, endpointUrl);
+
+ /* Connect Synchronous */
+ return connectSync(client);
}
/************************/
@@ -43453,6 +47341,11 @@ closeSecureChannel(UA_Client *client) {
/* Set the Session to "Created" if it was "Activated" */
if(client->sessionState > UA_SESSIONSTATE_CREATED)
client->sessionState = UA_SESSIONSTATE_CREATED;
+
+ /* Delete outstanding async services - the RequestId is no longr valid. Do
+ * this after setting the Session state. Otherwise we send out new Publish
+ * Requests immediately. */
+ UA_Client_AsyncService_removeAll(client, UA_STATUSCODE_BADSECURECHANNELCLOSED);
}
static void
@@ -43468,8 +47361,8 @@ sendCloseSession(UA_Client *client) {
UA_CloseSessionResponse response;
__UA_Client_Service(client, &request, &UA_TYPES[UA_TYPES_CLOSESESSIONREQUEST],
&response, &UA_TYPES[UA_TYPES_CLOSESESSIONRESPONSE]);
- UA_CloseSessionRequest_deleteMembers(&request);
- UA_CloseSessionResponse_deleteMembers(&response);
+ UA_CloseSessionRequest_clear(&request);
+ UA_CloseSessionResponse_clear(&response);
}
static void
@@ -43478,7 +47371,7 @@ closeSession(UA_Client *client) {
if(client->sessionState == UA_SESSIONSTATE_ACTIVATED)
sendCloseSession(client);
- UA_NodeId_deleteMembers(&client->authenticationToken);
+ UA_NodeId_clear(&client->authenticationToken);
client->requestHandle = 0;
client->sessionState = UA_SESSIONSTATE_CLOSED;
@@ -43540,7 +47433,7 @@ UA_Client_disconnect(UA_Client *client) {
}
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/src/client/ua_client_discovery.c" ***********************************/
+/**** amalgamated original file "/src/client/ua_client_discovery.c" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -43573,14 +47466,14 @@ UA_Client_getEndpointsInternal(UA_Client *client, const UA_String endpointUrl,
UA_LOG_ERROR(&client->config.logger, UA_LOGCATEGORY_CLIENT,
"GetEndpointRequest failed with error code %s",
UA_StatusCode_name(retval));
- UA_GetEndpointsResponse_deleteMembers(&response);
+ UA_GetEndpointsResponse_clear(&response);
return retval;
}
*endpointDescriptions = response.endpoints;
*endpointDescriptionsSize = response.endpointsSize;
response.endpoints = NULL;
response.endpointsSize = 0;
- UA_GetEndpointsResponse_deleteMembers(&response);
+ UA_GetEndpointsResponse_clear(&response);
return UA_STATUSCODE_GOOD;
}
@@ -43656,7 +47549,7 @@ UA_Client_findServers(UA_Client *client, const char *serverUrl,
}
/* Clean up */
- UA_FindServersResponse_deleteMembers(&response);
+ UA_FindServersResponse_clear(&response);
if(!connected)
UA_Client_disconnect(client);
return retval;
@@ -43709,7 +47602,7 @@ UA_Client_findServersOnNetwork(UA_Client *client, const char *serverUrl,
}
/* Clean up */
- UA_FindServersOnNetworkResponse_deleteMembers(&response);
+ UA_FindServersOnNetworkResponse_clear(&response);
if(!connected)
UA_Client_disconnect(client);
return retval;
@@ -43717,13 +47610,13 @@ UA_Client_findServersOnNetwork(UA_Client *client, const char *serverUrl,
#endif
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/src/client/ua_client_highlevel.c" ***********************************/
+/**** amalgamated original file "/src/client/ua_client_highlevel.c" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
- * Copyright 2015-2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
+ * Copyright 2015-2021 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
* Copyright 2015 (c) Oleksiy Vasylyev
* Copyright 2017 (c) Florian Palm
* Copyright 2016 (c) Chris Iatrou
@@ -43733,6 +47626,8 @@ UA_Client_findServersOnNetwork(UA_Client *client, const char *serverUrl,
*/
+/* The highlevel client API is an "outer onion layer". This file does not
+ * include ua_client_internal.h on purpose. */
UA_StatusCode
UA_Client_NamespaceGetIndex(UA_Client *client, UA_String *namespaceUri,
@@ -44090,7 +47985,7 @@ __UA_Client_readAttribute(UA_Client *client, const UA_NodeId *nodeId,
else
retval = UA_STATUSCODE_BADUNEXPECTEDERROR;
}
- if(retval != UA_STATUSCODE_GOOD) {
+ if(!UA_StatusCode_isEqualTop(retval,UA_STATUSCODE_GOOD)) {
UA_ReadResponse_clear(&response);
return retval;
}
@@ -44138,7 +48033,7 @@ processReadArrayDimensionsResult(UA_ReadResponse *response,
return UA_STATUSCODE_BADUNEXPECTEDERROR;
retval = response->results[0].status;
- if(retval != UA_STATUSCODE_GOOD)
+ if(!UA_StatusCode_isEqualTop(retval,UA_STATUSCODE_GOOD))
return retval;
UA_DataValue *res = &response->results[0];
@@ -44239,7 +48134,7 @@ cleanup: UA_HistoryReadResponse_clear(&response);
else
retval = UA_STATUSCODE_BADUNEXPECTEDERROR;
}
- if (retval != UA_STATUSCODE_GOOD)
+ if (!UA_StatusCode_isEqualTop(retval,UA_STATUSCODE_GOOD))
goto cleanup;
UA_HistoryReadResult *res = response.results;
@@ -44467,105 +48362,9 @@ cleanup:
}
#endif // UA_ENABLE_HISTORIZING
+/*******************/
/* Async Functions */
-
-typedef struct {
- UA_AttributeId attributeId;
- const UA_DataType *outDataType;
-} AsyncReadData;
-
-static CustomCallback *
-UA_Client_findCustomCallback(UA_Client *client, UA_UInt32 requestId) {
- CustomCallback *cc;
- LIST_FOREACH(cc, &client->customCallbacks, pointers) {
- if(cc->callbackId == requestId)
- break;
- }
- return cc;
-}
-
-static
-void ValueAttributeRead(UA_Client *client, void *userdata,
- UA_UInt32 requestId, void *response) {
- if(!response)
- return;
-
- /* Find the callback for the response */
- CustomCallback *cc = UA_Client_findCustomCallback(client, requestId);
- if(!cc)
- return;
-
- UA_ReadResponse *rr = (UA_ReadResponse *) response;
- UA_DataValue *res = rr->results;
- UA_Boolean done = false;
- AsyncReadData *data = (AsyncReadData *)cc->clientData;
- if(rr->resultsSize == 1 && res != NULL && res->hasValue) {
- if(data->attributeId == UA_ATTRIBUTEID_VALUE) {
- /* Call directly with the variant */
- cc->userCallback(client, cc->userData, requestId, &res->value);
- done = true;
- } else if(UA_Variant_isScalar(&res->value) &&
- res->value.type == data->outDataType) {
- /* Unpack the value */
- UA_STACKARRAY(UA_Byte, value, data->outDataType->memSize);
- memcpy(&value, res->value.data, data->outDataType->memSize);
- cc->userCallback(client, cc->userData, requestId, &value);
- done = true;
- }
- }
-
- /* Could not process, delete the callback anyway */
- if(!done)
- UA_LOG_INFO(&client->config.logger, UA_LOGCATEGORY_CLIENT,
- "Cannot process the response to the async read "
- "request %" PRIu32, requestId);
-
- UA_free(cc->clientData);
- LIST_REMOVE(cc, pointers);
- UA_free(cc);
-}
-
-/*Read Attributes*/
-UA_StatusCode
-__UA_Client_readAttribute_async(UA_Client *client,
- const UA_NodeId *nodeId, UA_AttributeId attributeId,
- const UA_DataType *outDataType, UA_ClientAsyncServiceCallback callback,
- void *userdata, UA_UInt32 *reqId) {
- UA_ReadValueId item;
- UA_ReadValueId_init(&item);
- item.nodeId = *nodeId;
- item.attributeId = attributeId;
- UA_ReadRequest request;
- UA_ReadRequest_init(&request);
- request.nodesToRead = &item;
- request.nodesToReadSize = 1;
-
- CustomCallback *cc = (CustomCallback*) UA_malloc(sizeof(CustomCallback));
- if (!cc)
- return UA_STATUSCODE_BADOUTOFMEMORY;
- memset(cc, 0, sizeof(CustomCallback));
- cc->userCallback = callback;
- cc->userData = userdata;
-
- cc->clientData = UA_malloc(sizeof(AsyncReadData));
- if(!cc->clientData) {
- UA_free(cc);
- return UA_STATUSCODE_BADOUTOFMEMORY;
- }
- AsyncReadData *rd = (AsyncReadData *)cc->clientData;
- rd->attributeId = attributeId;
- rd->outDataType = outDataType;
-
- __UA_Client_AsyncService(client, &request, &UA_TYPES[UA_TYPES_READREQUEST],
- ValueAttributeRead, &UA_TYPES[UA_TYPES_READRESPONSE], NULL,
- &cc->callbackId);
-
- LIST_INSERT_HEAD(&client->customCallbacks, cc, pointers);
- if (reqId != NULL)
- *reqId = cc->callbackId;
-
- return UA_STATUSCODE_GOOD;
-}
+/*******************/
/*Write Attributes*/
UA_StatusCode __UA_Client_writeAttribute_async(UA_Client *client,
@@ -44652,22 +48451,346 @@ UA_StatusCode __UA_Client_call_async(UA_Client *client,
}
#endif
-UA_StatusCode __UA_Client_translateBrowsePathsToNodeIds_async(UA_Client *client,
- char *paths[], UA_UInt32 ids[], size_t pathSize,
- UA_ClientAsyncServiceCallback callback, void *userdata,
- UA_UInt32 *reqId) {
- return UA_STATUSCODE_BADNOTIMPLEMENTED;
+/* UA_StatusCode */
+/* UA_Cient_translateBrowsePathsToNodeIds_async(UA_Client *client, char **paths, */
+/* UA_UInt32 *ids, size_t pathSize, */
+/* UA_ClientAsyncTranslateCallback callback, */
+/* void *userdata, UA_UInt32 *reqId) { */
+/* return UA_STATUSCODE_BADNOTIMPLEMENTED; */
+/* } */
+
+/*************************/
+/* Read Single Attribute */
+/*************************/
+
+typedef struct {
+ UA_ClientAsyncOperationCallback userCallback;
+ void *userContext;
+ const UA_DataType *resultType; /* DataValue -> Value attribute,
+ * Variant -> ArrayDimensions attribute */
+} UA_AttributeReadContext;
+
+static void
+AttributeReadCallback(UA_Client *client, void *userdata,
+ UA_UInt32 requestId, UA_ReadResponse *rr) {
+ UA_AttributeReadContext *ctx = (UA_AttributeReadContext*)userdata;
+ UA_LOG_DEBUG(&UA_Client_getConfig(client)->logger, UA_LOGCATEGORY_CLIENT,
+ "Async read response for request %" PRIu32, requestId);
+
+ /* Check the ServiceResult */
+ UA_StatusCode res = rr->responseHeader.serviceResult;
+ if(res != UA_STATUSCODE_GOOD)
+ goto finish;
+
+ /* Check result array size */
+ if(rr->resultsSize != 1) {
+ res = UA_STATUSCODE_BADINTERNALERROR;
+ goto finish;
+ }
+
+ /* A Value attribute */
+ UA_DataValue *dv = &rr->results[0];
+ if(ctx->resultType == &UA_TYPES[UA_TYPES_DATAVALUE]) {
+ ctx->userCallback(client, ctx->userContext, requestId,
+ UA_STATUSCODE_GOOD, dv);
+ goto finish;
+ }
+
+ /* An ArrayDimensions attribute. Has to be an array of UInt32. */
+ if(ctx->resultType == &UA_TYPES[UA_TYPES_VARIANT]) {
+ if(dv->hasValue &&
+ UA_Variant_hasArrayType(&dv->value, &UA_TYPES[UA_TYPES_UINT32])) {
+ ctx->userCallback(client, ctx->userContext, requestId,
+ UA_STATUSCODE_GOOD, &dv->value);
+ } else {
+ res = UA_STATUSCODE_BADINTERNALERROR;
+ }
+ goto finish;
+ }
+
+ /* Check we have a scalar value of the right datatype */
+ if(!dv->hasValue ||
+ !UA_Variant_hasScalarType(&dv->value, ctx->resultType)) {
+ res = UA_STATUSCODE_BADINTERNALERROR;
+ goto finish;
+ }
+
+ /* Callback into userland */
+ ctx->userCallback(client, ctx->userContext, requestId,
+ UA_STATUSCODE_GOOD, dv->value.data);
+
+ finish:
+ if(res != UA_STATUSCODE_GOOD)
+ ctx->userCallback(client, ctx->userContext, requestId, res, NULL);
+ UA_free(ctx);
+}
+
+static UA_StatusCode
+readAttribute_async(UA_Client *client, const UA_ReadValueId *rvi,
+ UA_TimestampsToReturn timestampsToReturn,
+ const UA_DataType *resultType, /* For the specialized reads */
+ UA_ClientAsyncOperationCallback callback,
+ void *userdata, UA_UInt32 *requestId) {
+ UA_AttributeReadContext *ctx = (UA_AttributeReadContext*)
+ UA_malloc(sizeof(UA_AttributeReadContext));
+ if(!ctx)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+
+ ctx->userCallback = callback;
+ ctx->userContext = userdata;
+ ctx->resultType = resultType;
+
+ UA_ReadRequest request;
+ UA_ReadRequest_init(&request);
+ request.nodesToRead = (UA_ReadValueId*)(uintptr_t)rvi; /* hack, treated as const */
+ request.nodesToReadSize = 1;
+ request.timestampsToReturn = timestampsToReturn;
+
+ UA_StatusCode res =
+ __UA_Client_AsyncService(client, &request, &UA_TYPES[UA_TYPES_READREQUEST],
+ (UA_ClientAsyncServiceCallback)AttributeReadCallback,
+ &UA_TYPES[UA_TYPES_READRESPONSE], ctx, requestId);
+ if(res != UA_STATUSCODE_GOOD)
+ UA_free(ctx);
+ return res;
}
UA_StatusCode
-UA_Cient_translateBrowsePathsToNodeIds_async(UA_Client *client, char **paths,
- UA_UInt32 *ids, size_t pathSize,
- UA_ClientAsyncTranslateCallback callback,
- void *userdata, UA_UInt32 *reqId) {
- return UA_STATUSCODE_BADNOTIMPLEMENTED;
+UA_Client_readAttribute_async(UA_Client *client, const UA_ReadValueId *rvi,
+ UA_TimestampsToReturn timestampsToReturn,
+ UA_ClientAsyncReadAttributeCallback callback,
+ void *userdata, UA_UInt32 *requestId) {
+ return readAttribute_async(client, rvi, timestampsToReturn,
+ &UA_TYPES[UA_TYPES_DATAVALUE], /* special handling */
+ (UA_ClientAsyncOperationCallback)callback,
+ userdata, requestId);
+}
+
+/* Helper to keep the code short */
+static UA_StatusCode
+readAttribute_simpleAsync(UA_Client *client, const UA_NodeId *nodeId,
+ UA_AttributeId attributeId, const UA_DataType *resultType,
+ UA_ClientAsyncOperationCallback callback,
+ void *userdata, UA_UInt32 *requestId) {
+ UA_ReadValueId rvi;
+ UA_ReadValueId_init(&rvi);
+ rvi.nodeId = *nodeId;
+ rvi.attributeId = attributeId;
+ return readAttribute_async(client, &rvi, UA_TIMESTAMPSTORETURN_NEITHER,
+ resultType, callback, userdata, requestId);
}
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/src/client/ua_client_subscriptions.c" ***********************************/
+UA_StatusCode
+UA_Client_readValueAttribute_async(UA_Client *client, const UA_NodeId nodeId,
+ UA_ClientAsyncReadValueAttributeCallback callback,
+ void *userdata, UA_UInt32 *requestId) {
+ return readAttribute_simpleAsync(client, &nodeId, UA_ATTRIBUTEID_VALUE,
+ &UA_TYPES[UA_TYPES_DATAVALUE], /* special hndling */
+ (UA_ClientAsyncOperationCallback)callback,
+ userdata, requestId);
+}
+
+UA_StatusCode
+UA_Client_readDataTypeAttribute_async(UA_Client *client, const UA_NodeId nodeId,
+ UA_ClientAsyncReadDataTypeAttributeCallback callback,
+ void *userdata, UA_UInt32 *requestId) {
+ return readAttribute_simpleAsync(client, &nodeId, UA_ATTRIBUTEID_DATATYPE,
+ &UA_TYPES[UA_TYPES_NODEID],
+ (UA_ClientAsyncOperationCallback)callback,
+ userdata, requestId);
+}
+
+UA_StatusCode
+UA_Client_readArrayDimensionsAttribute_async(UA_Client *client, const UA_NodeId nodeId,
+ UA_ClientReadArrayDimensionsAttributeCallback callback,
+ void *userdata, UA_UInt32 *requestId) {
+ return readAttribute_simpleAsync(client, &nodeId, UA_ATTRIBUTEID_ARRAYDIMENSIONS,
+ &UA_TYPES[UA_TYPES_VARIANT], /* special handling */
+ (UA_ClientAsyncOperationCallback)callback,
+ userdata, requestId);
+}
+
+UA_StatusCode
+UA_Client_readNodeClassAttribute_async(UA_Client *client, const UA_NodeId nodeId,
+ UA_ClientAsyncReadNodeClassAttributeCallback callback,
+ void *userdata, UA_UInt32 *requestId) {
+ return readAttribute_simpleAsync(client, &nodeId, UA_ATTRIBUTEID_NODECLASS,
+ &UA_TYPES[UA_TYPES_NODECLASS],
+ (UA_ClientAsyncOperationCallback)callback,
+ userdata, requestId);
+}
+
+UA_StatusCode
+UA_Client_readBrowseNameAttribute_async(UA_Client *client, const UA_NodeId nodeId,
+ UA_ClientAsyncReadBrowseNameAttributeCallback callback,
+ void *userdata, UA_UInt32 *requestId) {
+ return readAttribute_simpleAsync(client, &nodeId, UA_ATTRIBUTEID_BROWSENAME,
+ &UA_TYPES[UA_TYPES_QUALIFIEDNAME],
+ (UA_ClientAsyncOperationCallback)callback,
+ userdata, requestId);
+}
+
+UA_StatusCode
+UA_Client_readDisplayNameAttribute_async(UA_Client *client, const UA_NodeId nodeId,
+ UA_ClientAsyncReadDisplayNameAttributeCallback callback,
+ void *userdata, UA_UInt32 *requestId) {
+ return readAttribute_simpleAsync(client, &nodeId, UA_ATTRIBUTEID_DISPLAYNAME,
+ &UA_TYPES[UA_TYPES_LOCALIZEDTEXT],
+ (UA_ClientAsyncOperationCallback)callback,
+ userdata, requestId);
+}
+
+UA_StatusCode
+UA_Client_readDescriptionAttribute_async(UA_Client *client, const UA_NodeId nodeId,
+ UA_ClientAsyncReadDescriptionAttributeCallback callback,
+ void *userdata, UA_UInt32 *requestId) {
+ return readAttribute_simpleAsync(client, &nodeId, UA_ATTRIBUTEID_DESCRIPTION,
+ &UA_TYPES[UA_TYPES_LOCALIZEDTEXT],
+ (UA_ClientAsyncOperationCallback)callback,
+ userdata, requestId);
+}
+
+UA_StatusCode
+UA_Client_readWriteMaskAttribute_async(UA_Client *client, const UA_NodeId nodeId,
+ UA_ClientAsyncReadWriteMaskAttributeCallback callback,
+ void *userdata, UA_UInt32 *requestId) {
+ return readAttribute_simpleAsync(client, &nodeId, UA_ATTRIBUTEID_WRITEMASK,
+ &UA_TYPES[UA_TYPES_UINT32],
+ (UA_ClientAsyncOperationCallback)callback,
+ userdata, requestId);
+}
+
+UA_StatusCode UA_EXPORT
+UA_Client_readUserWriteMaskAttribute_async(UA_Client *client, const UA_NodeId nodeId,
+ UA_ClientAsyncReadUserWriteMaskAttributeCallback callback,
+ void *userdata, UA_UInt32 *requestId) {
+ return readAttribute_simpleAsync(client, &nodeId, UA_ATTRIBUTEID_USERWRITEMASK,
+ &UA_TYPES[UA_TYPES_UINT32],
+ (UA_ClientAsyncOperationCallback)callback,
+ userdata, requestId);
+}
+
+UA_StatusCode
+UA_Client_readIsAbstractAttribute_async(UA_Client *client, const UA_NodeId nodeId,
+ UA_ClientAsyncReadIsAbstractAttributeCallback callback,
+ void *userdata, UA_UInt32 *requestId) {
+ return readAttribute_simpleAsync(client, &nodeId, UA_ATTRIBUTEID_ISABSTRACT,
+ &UA_TYPES[UA_TYPES_BOOLEAN],
+ (UA_ClientAsyncOperationCallback)callback,
+ userdata, requestId);
+}
+
+UA_StatusCode
+UA_Client_readSymmetricAttribute_async(UA_Client *client, const UA_NodeId nodeId,
+ UA_ClientAsyncReadSymmetricAttributeCallback callback,
+ void *userdata, UA_UInt32 *requestId) {
+ return readAttribute_simpleAsync(client, &nodeId, UA_ATTRIBUTEID_SYMMETRIC,
+ &UA_TYPES[UA_TYPES_BOOLEAN],
+ (UA_ClientAsyncOperationCallback)callback,
+ userdata, requestId);
+}
+
+UA_StatusCode
+UA_Client_readInverseNameAttribute_async(UA_Client *client, const UA_NodeId nodeId,
+ UA_ClientAsyncReadInverseNameAttributeCallback callback,
+ void *userdata, UA_UInt32 *requestId) {
+ return readAttribute_simpleAsync(client, &nodeId, UA_ATTRIBUTEID_INVERSENAME,
+ &UA_TYPES[UA_TYPES_LOCALIZEDTEXT],
+ (UA_ClientAsyncOperationCallback)callback,
+ userdata, requestId);
+}
+
+UA_StatusCode
+UA_Client_readContainsNoLoopsAttribute_async(UA_Client *client, const UA_NodeId nodeId,
+ UA_ClientAsyncReadContainsNoLoopsAttributeCallback callback,
+ void *userdata, UA_UInt32 *requestId) {
+ return readAttribute_simpleAsync(client, &nodeId, UA_ATTRIBUTEID_CONTAINSNOLOOPS,
+ &UA_TYPES[UA_TYPES_BOOLEAN],
+ (UA_ClientAsyncOperationCallback)callback,
+ userdata, requestId);
+}
+
+UA_StatusCode
+UA_Client_readEventNotifierAttribute_async(UA_Client *client, const UA_NodeId nodeId,
+ UA_ClientAsyncReadEventNotifierAttributeCallback callback,
+ void *userdata, UA_UInt32 *requestId) {
+ return readAttribute_simpleAsync(client, &nodeId, UA_ATTRIBUTEID_EVENTNOTIFIER,
+ &UA_TYPES[UA_TYPES_BYTE],
+ (UA_ClientAsyncOperationCallback)callback,
+ userdata, requestId);
+}
+
+UA_StatusCode
+UA_Client_readValueRankAttribute_async(UA_Client *client, const UA_NodeId nodeId,
+ UA_ClientAsyncReadValueRankAttributeCallback callback,
+ void *userdata, UA_UInt32 *requestId) {
+ return readAttribute_simpleAsync(client, &nodeId, UA_ATTRIBUTEID_VALUERANK,
+ &UA_TYPES[UA_TYPES_INT32],
+ (UA_ClientAsyncOperationCallback)callback,
+ userdata, requestId);
+}
+
+UA_StatusCode
+UA_Client_readAccessLevelAttribute_async(UA_Client *client, const UA_NodeId nodeId,
+ UA_ClientAsyncReadAccessLevelAttributeCallback callback,
+ void *userdata, UA_UInt32 *requestId) {
+ return readAttribute_simpleAsync(client, &nodeId, UA_ATTRIBUTEID_ACCESSLEVEL,
+ &UA_TYPES[UA_TYPES_BYTE],
+ (UA_ClientAsyncOperationCallback)callback,
+ userdata, requestId);
+}
+
+UA_StatusCode
+UA_Client_readUserAccessLevelAttribute_async(UA_Client *client, const UA_NodeId nodeId,
+ UA_ClientAsyncReadUserAccessLevelAttributeCallback callback,
+ void *userdata, UA_UInt32 *requestId) {
+ return readAttribute_simpleAsync(client, &nodeId, UA_ATTRIBUTEID_USERACCESSLEVEL,
+ &UA_TYPES[UA_TYPES_BYTE],
+ (UA_ClientAsyncOperationCallback)callback,
+ userdata, requestId);
+}
+
+UA_StatusCode
+UA_Client_readMinimumSamplingIntervalAttribute_async(UA_Client *client, const UA_NodeId nodeId,
+ UA_ClientAsyncReadMinimumSamplingIntervalAttributeCallback callback,
+ void *userdata, UA_UInt32 *requestId) {
+ return readAttribute_simpleAsync(client, &nodeId, UA_ATTRIBUTEID_MINIMUMSAMPLINGINTERVAL,
+ &UA_TYPES[UA_TYPES_DOUBLE],
+ (UA_ClientAsyncOperationCallback)callback,
+ userdata, requestId);
+}
+
+UA_StatusCode
+UA_Client_readHistorizingAttribute_async(UA_Client *client, const UA_NodeId nodeId,
+ UA_ClientAsyncReadHistorizingAttributeCallback callback,
+ void *userdata, UA_UInt32 *requestId) {
+ return readAttribute_simpleAsync(client, &nodeId, UA_ATTRIBUTEID_HISTORIZING,
+ &UA_TYPES[UA_TYPES_BOOLEAN],
+ (UA_ClientAsyncOperationCallback)callback,
+ userdata, requestId);
+}
+
+UA_StatusCode
+UA_Client_readExecutableAttribute_async(UA_Client *client, const UA_NodeId nodeId,
+ UA_ClientAsyncReadExecutableAttributeCallback callback,
+ void *userdata, UA_UInt32 *requestId) {
+ return readAttribute_simpleAsync(client, &nodeId, UA_ATTRIBUTEID_EXECUTABLE,
+ &UA_TYPES[UA_TYPES_BOOLEAN],
+ (UA_ClientAsyncOperationCallback)callback,
+ userdata, requestId);
+}
+
+UA_StatusCode
+UA_Client_readUserExecutableAttribute_async(UA_Client *client, const UA_NodeId nodeId,
+ UA_ClientAsyncReadUserExecutableAttributeCallback callback,
+ void *userdata, UA_UInt32 *requestId) {
+ return readAttribute_simpleAsync(client, &nodeId, UA_ATTRIBUTEID_USEREXECUTABLE,
+ &UA_TYPES[UA_TYPES_BOOLEAN],
+ (UA_ClientAsyncOperationCallback)callback,
+ userdata, requestId);
+}
+
+/**** amalgamated original file "/src/client/ua_client_subscriptions.c" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -44691,21 +48814,12 @@ UA_Cient_translateBrowsePathsToNodeIds_async(UA_Client *client, char **paths,
/*****************/
static void
-UA_Client_MonitoredItem_remove(UA_Client *client, UA_Client_Subscription *sub,
- UA_Client_MonitoredItem *mon);
+MonitoredItem_delete(UA_Client *client, UA_Client_Subscription *sub,
+ UA_Client_MonitoredItem *mon);
static void
-__Subscriptions_create_handler(UA_Client *client, void *data, UA_UInt32 requestId, void *r) {
- UA_CreateSubscriptionResponse *response = (UA_CreateSubscriptionResponse *)r;
- CustomCallback *cc = (CustomCallback *)data;
- if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
- if(cc->clientData)
- UA_free(cc->clientData);
- goto cleanup;
- }
-
- /* Prepare the internal representation */
- UA_Client_Subscription *newSub = (UA_Client_Subscription *)cc->clientData;
+ua_Subscriptions_create(UA_Client *client, UA_Client_Subscription *newSub,
+ UA_CreateSubscriptionResponse *response) {
newSub->subscriptionId = response->subscriptionId;
newSub->sequenceNumber = 0;
newSub->lastActivity = UA_DateTime_nowMonotonic();
@@ -44713,13 +48827,26 @@ __Subscriptions_create_handler(UA_Client *client, void *data, UA_UInt32 requestI
newSub->maxKeepAliveCount = response->revisedMaxKeepAliveCount;
LIST_INIT(&newSub->monitoredItems);
LIST_INSERT_HEAD(&client->subscriptions, newSub, listEntry);
+}
-cleanup:
- if(cc->isAsync) {
- if(cc->userCallback)
- cc->userCallback(client, cc->userData, requestId, response);
- UA_free(cc);
+static void
+ua_Subscriptions_create_handler(UA_Client *client, void *data, UA_UInt32 requestId,
+ void *r) {
+ UA_CreateSubscriptionResponse *response = (UA_CreateSubscriptionResponse *)r;
+ CustomCallback *cc = (CustomCallback *)data;
+ UA_Client_Subscription *newSub = (UA_Client_Subscription *)cc->clientData;
+ if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
+ UA_free(newSub);
+ goto cleanup;
}
+
+ /* Prepare the internal representation */
+ ua_Subscriptions_create(client, newSub, response);
+
+cleanup:
+ if(cc->userCallback)
+ cc->userCallback(client, cc->userData, requestId, response);
+ UA_free(cc);
}
UA_CreateSubscriptionResponse
@@ -44729,48 +48856,39 @@ UA_Client_Subscriptions_create(UA_Client *client,
UA_Client_StatusChangeNotificationCallback statusChangeCallback,
UA_Client_DeleteSubscriptionCallback deleteCallback) {
UA_CreateSubscriptionResponse response;
- UA_CreateSubscriptionResponse_init(&response);
-
- CustomCallback cc;
- memset(&cc, 0, sizeof(CustomCallback));
-#ifdef __clang_analyzer__
- cc.isAsync = false;
-#endif
-
UA_Client_Subscription *sub = (UA_Client_Subscription *)
UA_malloc(sizeof(UA_Client_Subscription));
if(!sub) {
+ UA_CreateSubscriptionResponse_init(&response);
response.responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
return response;
}
sub->context = subscriptionContext;
sub->statusChangeCallback = statusChangeCallback;
sub->deleteCallback = deleteCallback;
- cc.clientData = sub;
/* Send the request as a synchronous service call */
__UA_Client_Service(client,
&request, &UA_TYPES[UA_TYPES_CREATESUBSCRIPTIONREQUEST],
&response, &UA_TYPES[UA_TYPES_CREATESUBSCRIPTIONRESPONSE]);
- __Subscriptions_create_handler(client, &cc, 0, &response);
+ ua_Subscriptions_create(client, sub, &response);
return response;
}
UA_StatusCode
-UA_Client_Subscriptions_create_async(UA_Client *client, const UA_CreateSubscriptionRequest request,
+UA_Client_Subscriptions_create_async(UA_Client *client,
+ const UA_CreateSubscriptionRequest request,
void *subscriptionContext,
UA_Client_StatusChangeNotificationCallback statusChangeCallback,
UA_Client_DeleteSubscriptionCallback deleteCallback,
- UA_ClientAsyncServiceCallback createCallback, void *userdata,
+ UA_ClientAsyncServiceCallback createCallback,
+ void *userdata,
UA_UInt32 *requestId) {
CustomCallback *cc = (CustomCallback *)UA_calloc(1, sizeof(CustomCallback));
if(!cc)
return UA_STATUSCODE_BADOUTOFMEMORY;
- cc->isAsync = true;
- cc->userCallback = createCallback;
- cc->userData = userdata;
UA_Client_Subscription *sub = (UA_Client_Subscription *)
UA_malloc(sizeof(UA_Client_Subscription));
@@ -44781,14 +48899,16 @@ UA_Client_Subscriptions_create_async(UA_Client *client, const UA_CreateSubscript
sub->context = subscriptionContext;
sub->statusChangeCallback = statusChangeCallback;
sub->deleteCallback = deleteCallback;
+
+ cc->userCallback = createCallback;
+ cc->userData = userdata;
cc->clientData = sub;
/* Send the request as asynchronous service call */
- return __UA_Client_AsyncService(client, &request,
- &UA_TYPES[UA_TYPES_CREATESUBSCRIPTIONREQUEST],
- __Subscriptions_create_handler,
- &UA_TYPES[UA_TYPES_CREATESUBSCRIPTIONRESPONSE],
- cc, requestId);
+ return __UA_Client_AsyncService(
+ client, &request, &UA_TYPES[UA_TYPES_CREATESUBSCRIPTIONREQUEST],
+ ua_Subscriptions_create_handler, &UA_TYPES[UA_TYPES_CREATESUBSCRIPTIONRESPONSE],
+ cc, requestId);
}
static UA_Client_Subscription *
@@ -44802,23 +48922,35 @@ findSubscription(const UA_Client *client, UA_UInt32 subscriptionId) {
}
static void
-__Subscriptions_modify_handler(UA_Client *client, void *data, UA_UInt32 requestId, void *r) {
- UA_ModifySubscriptionResponse *response = (UA_ModifySubscriptionResponse *)r;
- CustomCallback *cc = (CustomCallback *)data;
- UA_Client_Subscription *sub = (UA_Client_Subscription *)cc->clientData;
-
+ua_Subscriptions_modify(UA_Client *client, UA_Client_Subscription *sub,
+ const UA_ModifySubscriptionResponse *response) {
sub->publishingInterval = response->revisedPublishingInterval;
sub->maxKeepAliveCount = response->revisedMaxKeepAliveCount;
+}
- if(cc->isAsync) {
- if(cc->userCallback)
- cc->userCallback(client, cc->userData, requestId, response);
- UA_free(cc);
+static void
+ua_Subscriptions_modify_handler(UA_Client *client, void *data, UA_UInt32 requestId,
+ void *r) {
+ UA_ModifySubscriptionResponse *response = (UA_ModifySubscriptionResponse *)r;
+ CustomCallback *cc = (CustomCallback *)data;
+ UA_Client_Subscription *sub =
+ findSubscription(client, (UA_UInt32)(uintptr_t)cc->clientData);
+ if(sub) {
+ ua_Subscriptions_modify(client, sub, response);
+ } else {
+ UA_LOG_INFO(&client->config.logger, UA_LOGCATEGORY_CLIENT,
+ "No internal representation of subscription %" PRIu32,
+ (UA_UInt32)(uintptr_t)cc->clientData);
}
+
+ if(cc->userCallback)
+ cc->userCallback(client, cc->userData, requestId, response);
+ UA_free(cc);
}
UA_ModifySubscriptionResponse
-UA_Client_Subscriptions_modify(UA_Client *client, const UA_ModifySubscriptionRequest request) {
+UA_Client_Subscriptions_modify(UA_Client *client,
+ const UA_ModifySubscriptionRequest request) {
UA_ModifySubscriptionResponse response;
UA_ModifySubscriptionResponse_init(&response);
@@ -44835,8 +48967,7 @@ UA_Client_Subscriptions_modify(UA_Client *client, const UA_ModifySubscriptionReq
&response, &UA_TYPES[UA_TYPES_MODIFYSUBSCRIPTIONRESPONSE]);
/* Adjust the internal representation */
- sub->publishingInterval = response.revisedPublishingInterval;
- sub->maxKeepAliveCount = response.revisedMaxKeepAliveCount;
+ ua_Subscriptions_modify(client, sub, &response);
return response;
}
@@ -44854,24 +48985,24 @@ UA_Client_Subscriptions_modify_async(UA_Client *client,
if(!cc)
return UA_STATUSCODE_BADOUTOFMEMORY;
- cc->isAsync = true;
- cc->clientData = sub;
+ cc->clientData = (void *)(uintptr_t)request.subscriptionId;
cc->userData = userdata;
cc->userCallback = callback;
- return __UA_Client_AsyncService(client, &request,
- &UA_TYPES[UA_TYPES_MODIFYSUBSCRIPTIONREQUEST],
- __Subscriptions_modify_handler,
- &UA_TYPES[UA_TYPES_MODIFYSUBSCRIPTIONRESPONSE],
- cc, requestId);
+ return __UA_Client_AsyncService(
+ client, &request, &UA_TYPES[UA_TYPES_MODIFYSUBSCRIPTIONREQUEST],
+ ua_Subscriptions_modify_handler, &UA_TYPES[UA_TYPES_MODIFYSUBSCRIPTIONRESPONSE],
+ cc, requestId);
}
static void
-UA_Client_Subscription_deleteInternal(UA_Client *client, UA_Client_Subscription *sub) {
+UA_Client_Subscription_deleteInternal(UA_Client *client,
+ UA_Client_Subscription *sub) {
/* Remove the MonitoredItems */
- UA_Client_MonitoredItem *mon, *mon_tmp;
+ UA_Client_MonitoredItem *mon;
+ UA_Client_MonitoredItem *mon_tmp;
LIST_FOREACH_SAFE(mon, &sub->monitoredItems, listEntry, mon_tmp)
- UA_Client_MonitoredItem_remove(client, sub, mon);
+ MonitoredItem_delete(client, sub, mon);
/* Call the delete callback */
if(sub->deleteCallback)
@@ -44882,84 +49013,61 @@ UA_Client_Subscription_deleteInternal(UA_Client *client, UA_Client_Subscription
UA_free(sub);
}
-typedef struct {
- UA_DeleteSubscriptionsRequest *request;
- UA_Client_Subscription **subs;
-} Subscriptions_DeleteData;
-
static void
-__Subscriptions_DeleteData_free(Subscriptions_DeleteData *data) {
- if(!data)
- return;
- if(data->subs)
- UA_free(data->subs);
- if(data->request)
- UA_delete(data->request, &UA_TYPES[UA_TYPES_DELETESUBSCRIPTIONSREQUEST]);
- UA_free(data);
-}
-
-static UA_INLINE void
-__Subscriptions_delete_prepare(UA_Client *client, Subscriptions_DeleteData *data) {
- /* temporary remove the subscriptions from the list */
- for(size_t i = 0; i < data->request->subscriptionIdsSize; i++) {
- data->subs[i] = findSubscription(client, data->request->subscriptionIds[i]);
- if(data->subs[i])
- LIST_REMOVE(data->subs[i], listEntry);
- }
-}
-
-static void
-__Subscriptions_delete_handler(UA_Client *client, void *data, UA_UInt32 requestId, void *r) {
- UA_DeleteSubscriptionsResponse *response = (UA_DeleteSubscriptionsResponse *)r;
- CustomCallback *cc = (CustomCallback *)data;
- Subscriptions_DeleteData *delData = (Subscriptions_DeleteData *)cc->clientData;
- UA_DeleteSubscriptionsRequest *request = delData->request;
- UA_Client_Subscription **subs = delData->subs;
-
+UA_Client_Subscription_processDelete(UA_Client *client,
+ const UA_DeleteSubscriptionsRequest *request,
+ const UA_DeleteSubscriptionsResponse *response) {
if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD)
- goto cleanup;
+ return;
- if(request->subscriptionIdsSize != response->resultsSize) {
- response->responseHeader.serviceResult = UA_STATUSCODE_BADINTERNALERROR;
- goto cleanup;
- }
+ /* Check that the request and response size -- use the same index for both */
+ if(request->subscriptionIdsSize != response->resultsSize)
+ return;
- /* Loop over the removed subscriptions and remove internally */
for(size_t i = 0; i < request->subscriptionIdsSize; i++) {
if(response->results[i] != UA_STATUSCODE_GOOD &&
- response->results[i] != UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID) {
- /* Something was wrong, reinsert the subscription in the list */
- if(subs[i])
- LIST_INSERT_HEAD(&client->subscriptions, subs[i], listEntry);
+ response->results[i] != UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID)
continue;
- }
- if(!subs[i]) {
+ /* Get the Subscription */
+ UA_Client_Subscription *sub =
+ findSubscription(client, request->subscriptionIds[i]);
+ if(!sub) {
UA_LOG_INFO(&client->config.logger, UA_LOGCATEGORY_CLIENT,
"No internal representation of subscription %" PRIu32,
- delData->request->subscriptionIds[i]);
+ request->subscriptionIds[i]);
continue;
}
- LIST_INSERT_HEAD(&client->subscriptions, subs[i], listEntry);
- UA_Client_Subscription_deleteInternal(client, subs[i]);
+ /* Delete the Subscription */
+ UA_Client_Subscription_deleteInternal(client, sub);
}
-cleanup:
- if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
- for(size_t i = 0; i < request->subscriptionIdsSize; i++) {
- if(subs[i]) {
- LIST_INSERT_HEAD(&client->subscriptions, subs[i], listEntry);
- }
- }
- }
+}
- if(cc->isAsync) {
- if(cc->userCallback)
- cc->userCallback(client, cc->userData, requestId, response);
- __Subscriptions_DeleteData_free(delData);
- UA_free(cc);
- }
+typedef struct {
+ UA_DeleteSubscriptionsRequest request;
+ UA_ClientAsyncServiceCallback userCallback;
+ void *userData;
+} DeleteSubscriptionCallback;
+
+static void
+ua_Subscriptions_delete_handler(UA_Client *client, void *data, UA_UInt32 requestId,
+ void *r) {
+ UA_DeleteSubscriptionsResponse *response =
+ (UA_DeleteSubscriptionsResponse *)r;
+ DeleteSubscriptionCallback *dsc =
+ (DeleteSubscriptionCallback*)data;
+
+ /* Delete */
+ UA_Client_Subscription_processDelete(client, &dsc->request, response);
+
+ /* Userland Callback */
+ dsc->userCallback(client, dsc->userData, requestId, response);
+
+ /* Cleanup */
+ UA_DeleteSubscriptionsRequest_clear(&dsc->request);
+ UA_free(dsc);
}
UA_StatusCode
@@ -44967,66 +49075,36 @@ UA_Client_Subscriptions_delete_async(UA_Client *client,
const UA_DeleteSubscriptionsRequest request,
UA_ClientAsyncServiceCallback callback,
void *userdata, UA_UInt32 *requestId) {
- CustomCallback *cc = (CustomCallback *)UA_calloc(1, sizeof(CustomCallback));
- if(!cc)
+ /* Make a copy of the request that persists into the async callback */
+ DeleteSubscriptionCallback *dsc =
+ (DeleteSubscriptionCallback*)UA_malloc(sizeof(DeleteSubscriptionCallback));
+ if(!dsc)
return UA_STATUSCODE_BADOUTOFMEMORY;
+ dsc->userCallback = callback;
+ dsc->userData = userdata;
+ UA_StatusCode res = UA_DeleteSubscriptionsRequest_copy(&request, &dsc->request);
+ if(res != UA_STATUSCODE_GOOD) {
+ UA_free(dsc);
+ return res;
+ }
- Subscriptions_DeleteData *data = (Subscriptions_DeleteData *)
- UA_calloc(1, sizeof(Subscriptions_DeleteData));
- if(cc->clientData)
- goto cleanup;
- cc->clientData = data;
- data->subs = (UA_Client_Subscription **)
- UA_calloc(request.subscriptionIdsSize, sizeof(UA_Client_Subscription *));
- if(!data->subs)
- goto cleanup;
-
- data->request = UA_DeleteSubscriptionsRequest_new();
- if(!data->request)
- goto cleanup;
- UA_DeleteSubscriptionsRequest_copy(&request, data->request);
-
- __Subscriptions_delete_prepare(client, data);
- cc->isAsync = true;
- cc->userCallback = callback;
- cc->userData = userdata;
-
- return __UA_Client_AsyncService(client, &request, &UA_TYPES[UA_TYPES_DELETESUBSCRIPTIONSREQUEST],
- __Subscriptions_delete_handler,
- &UA_TYPES[UA_TYPES_DELETESUBSCRIPTIONSRESPONSE],
- cc, requestId);
-cleanup:
- __Subscriptions_DeleteData_free(data);
- UA_free(cc);
- return UA_STATUSCODE_BADOUTOFMEMORY;
+ /* Make the async call */
+ return __UA_Client_AsyncService(
+ client, &request, &UA_TYPES[UA_TYPES_DELETESUBSCRIPTIONSREQUEST],
+ ua_Subscriptions_delete_handler, &UA_TYPES[UA_TYPES_DELETESUBSCRIPTIONSRESPONSE],
+ dsc, requestId);
}
UA_DeleteSubscriptionsResponse
UA_Client_Subscriptions_delete(UA_Client *client,
const UA_DeleteSubscriptionsRequest request) {
- UA_STACKARRAY(UA_Client_Subscription *, subs, request.subscriptionIdsSize);
- memset(subs, 0, sizeof(void *) * request.subscriptionIdsSize);
-
- CustomCallback cc;
- memset(&cc, 0, sizeof(CustomCallback));
-#ifdef __clang_analyzer__
- cc.isAsync = false;
-#endif
-
- Subscriptions_DeleteData data;
- cc.clientData = &data;
- data.request = (UA_DeleteSubscriptionsRequest *)(uintptr_t)&request;
- data.subs = subs;
-
- __Subscriptions_delete_prepare(client, &data);
-
/* Send the request */
UA_DeleteSubscriptionsResponse response;
-
__UA_Client_Service(client, &request, &UA_TYPES[UA_TYPES_DELETESUBSCRIPTIONSREQUEST],
&response, &UA_TYPES[UA_TYPES_DELETESUBSCRIPTIONSRESPONSE]);
- __Subscriptions_delete_handler(client, &cc, 0, &response);
+ /* Process */
+ UA_Client_Subscription_processDelete(client, &request, &response);
return response;
}
@@ -45042,17 +49120,17 @@ UA_Client_Subscriptions_deleteSingle(UA_Client *client, UA_UInt32 subscriptionId
UA_StatusCode retval = response.responseHeader.serviceResult;
if(retval != UA_STATUSCODE_GOOD) {
- UA_DeleteSubscriptionsResponse_deleteMembers(&response);
+ UA_DeleteSubscriptionsResponse_clear(&response);
return retval;
}
if(response.resultsSize != 1) {
- UA_DeleteSubscriptionsResponse_deleteMembers(&response);
+ UA_DeleteSubscriptionsResponse_clear(&response);
return UA_STATUSCODE_BADINTERNALERROR;
}
retval = response.results[0];
- UA_DeleteSubscriptionsResponse_deleteMembers(&response);
+ UA_DeleteSubscriptionsResponse_clear(&response);
return retval;
}
@@ -45061,9 +49139,8 @@ UA_Client_Subscriptions_deleteSingle(UA_Client *client, UA_UInt32 subscriptionId
/******************/
static void
-UA_Client_MonitoredItem_remove(UA_Client *client, UA_Client_Subscription *sub,
- UA_Client_MonitoredItem *mon) {
- // NOLINTNEXTLINE
+MonitoredItem_delete(UA_Client *client, UA_Client_Subscription *sub,
+ UA_Client_MonitoredItem *mon) {
LIST_REMOVE(mon, listEntry);
if(mon->deleteCallback)
mon->deleteCallback(client, sub->subscriptionId, sub->context,
@@ -45072,129 +49149,155 @@ UA_Client_MonitoredItem_remove(UA_Client *client, UA_Client_Subscription *sub,
}
typedef struct {
- UA_Client_Subscription *sub;
-
- UA_Client_MonitoredItem **mis;
void **contexts;
UA_Client_DeleteMonitoredItemCallback *deleteCallbacks;
void **handlingCallbacks;
+ UA_CreateMonitoredItemsRequest request;
- UA_CreateMonitoredItemsRequest *request;
+ /* Notify the user that the async callback was processed */
+ UA_ClientAsyncServiceCallback userCallback;
+ void *userData;
} MonitoredItems_CreateData;
static void
-MonitoredItems_CreateData_deleteItems(UA_Client_MonitoredItem **mis,
- MonitoredItems_CreateData *data, UA_Client *client) {
- bool hasCallbacks = (data->deleteCallbacks && data->contexts);
- for(size_t i = 0; i < data->request->itemsToCreateSize; i++) {
- if(!mis[i])
- continue;
- UA_free(mis[i]);
- mis[i] = NULL;
- if(hasCallbacks && data->deleteCallbacks[i]) {
- if(data->sub)
- data->deleteCallbacks[i](client, data->sub->subscriptionId,
- data->sub->context, 0, data->contexts[i]);
- else
- data->deleteCallbacks[i](client, 0, NULL, 0, data->contexts[i]);
- }
- }
+MonitoredItems_CreateData_clear(UA_Client *client, MonitoredItems_CreateData *data) {
+ UA_free(data->contexts);
+ UA_free(data->deleteCallbacks);
+ UA_free(data->handlingCallbacks);
+ UA_CreateMonitoredItemsRequest_clear(&data->request);
}
static void
-__MonitoredItems_create_handler(UA_Client *client, CustomCallback *cc, UA_UInt32 requestId,
- UA_CreateMonitoredItemsResponse *response) {
- MonitoredItems_CreateData *data = (MonitoredItems_CreateData *)cc->clientData;
-
- // introduce local pointers to the variables/parameters in the CreateData
- // to keep the code completely intact
- UA_CreateMonitoredItemsRequest *request = data->request;
+ua_MonitoredItems_create(UA_Client *client, MonitoredItems_CreateData *data,
+ UA_CreateMonitoredItemsResponse *response) {
+ UA_CreateMonitoredItemsRequest *request = &data->request;
UA_Client_DeleteMonitoredItemCallback *deleteCallbacks = data->deleteCallbacks;
- UA_Client_Subscription *sub = data->sub;
- void **contexts = data->contexts;
- UA_Client_MonitoredItem **mis = data->mis;
- void **handlingCallbacks = data->handlingCallbacks;
+
+ UA_Client_Subscription *sub = findSubscription(client, data->request.subscriptionId);
+ if(!sub)
+ goto cleanup;
if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD)
- return;
+ goto cleanup;
if(response->resultsSize != request->itemsToCreateSize) {
response->responseHeader.serviceResult = UA_STATUSCODE_BADINTERNALERROR;
- return;
+ goto cleanup;
}
/* Add internally */
for(size_t i = 0; i < request->itemsToCreateSize; i++) {
if(response->results[i].statusCode != UA_STATUSCODE_GOOD) {
if(deleteCallbacks[i])
- deleteCallbacks[i](client, sub->subscriptionId, sub->context, 0, contexts[i]);
- UA_free(mis[i]);
- mis[i] = NULL;
+ deleteCallbacks[i](client, sub->subscriptionId, sub->context,
+ 0, data->contexts[i]);
+ continue;
+ }
+
+ UA_Client_MonitoredItem *newMon = (UA_Client_MonitoredItem *)
+ UA_malloc(sizeof(UA_Client_MonitoredItem));
+ if(!newMon) {
+ if(deleteCallbacks[i])
+ deleteCallbacks[i](client, sub->subscriptionId, sub->context, 0,
+ data->contexts[i]);
continue;
}
- UA_assert(mis[i] != NULL);
- UA_Client_MonitoredItem *newMon = mis[i];
- newMon->clientHandle = request->itemsToCreate[i].requestedParameters.clientHandle;
newMon->monitoredItemId = response->results[i].monitoredItemId;
- newMon->context = contexts[i];
+ newMon->clientHandle = request->itemsToCreate[i].requestedParameters.clientHandle;
+ newMon->context = data->contexts[i];
newMon->deleteCallback = deleteCallbacks[i];
newMon->handler.dataChangeCallback =
- (UA_Client_DataChangeNotificationCallback)(uintptr_t)handlingCallbacks[i];
+ (UA_Client_DataChangeNotificationCallback)(uintptr_t)
+ data->handlingCallbacks[i];
newMon->isEventMonitoredItem =
- (request->itemsToCreate[i].itemToMonitor.attributeId == UA_ATTRIBUTEID_EVENTNOTIFIER);
+ (request->itemsToCreate[i].itemToMonitor.attributeId ==
+ UA_ATTRIBUTEID_EVENTNOTIFIER);
LIST_INSERT_HEAD(&sub->monitoredItems, newMon, listEntry);
UA_LOG_DEBUG(&client->config.logger, UA_LOGCATEGORY_CLIENT,
- "Subscription %" PRIu32 " | Added a MonitoredItem with handle %" PRIu32,
+ "Subscription %" PRIu32
+ " | Added a MonitoredItem with handle %" PRIu32,
sub->subscriptionId, newMon->clientHandle);
- mis[i] = NULL;
+ }
+ return;
+
+ /* Adding failed */
+ cleanup:
+ for(size_t i = 0; i < request->itemsToCreateSize; i++) {
+ if(deleteCallbacks[i])
+ deleteCallbacks[i](client, data->request.subscriptionId,
+ sub ? sub->context : NULL, 0, data->contexts[i]);
}
}
static void
-__MonitoredItems_create_async_handler(UA_Client *client, void *d,
- UA_UInt32 requestId, void *r) {
+ua_MonitoredItems_create_async_handler(UA_Client *client, void *d, UA_UInt32 requestId,
+ void *r) {
UA_CreateMonitoredItemsResponse *response = (UA_CreateMonitoredItemsResponse *)r;
- CustomCallback *cc = (CustomCallback *)d;
- MonitoredItems_CreateData *data = (MonitoredItems_CreateData *)cc->clientData;
+ MonitoredItems_CreateData *data = (MonitoredItems_CreateData *)d;
- __MonitoredItems_create_handler(client, cc, requestId, response);
- MonitoredItems_CreateData_deleteItems(data->mis, data, client);
- if(cc->userCallback)
- cc->userCallback(client, cc->userData, requestId, response);
- UA_free(cc);
- if(data->mis)
- UA_free(data->mis);
- if(data->request)
- UA_CreateMonitoredItemsRequest_delete(data->request);
+ ua_MonitoredItems_create(client, data, response);
+
+ if(data->userCallback)
+ data->userCallback(client, data->userData, requestId, response);
+
+ MonitoredItems_CreateData_clear(client, data);
UA_free(data);
}
static UA_StatusCode
-MonitoredItems_CreateData_prepare(UA_Client_MonitoredItem **mis,
- MonitoredItems_CreateData *data, UA_Client *client) {
- /* Allocate the memory for internal representations */
- for(size_t i = 0; i < data->request->itemsToCreateSize; i++) {
- mis[i] = (UA_Client_MonitoredItem *)UA_malloc(sizeof(UA_Client_MonitoredItem));
- if(!mis[i])
- return UA_STATUSCODE_BADOUTOFMEMORY;
- }
+MonitoredItems_CreateData_prepare(UA_Client *client,
+ const UA_CreateMonitoredItemsRequest *request,
+ void **contexts, void **handlingCallbacks,
+ UA_Client_DeleteMonitoredItemCallback *deleteCallbacks,
+ MonitoredItems_CreateData *data) {
+ /* Align arrays and copy over */
+ UA_StatusCode retval = UA_STATUSCODE_BADOUTOFMEMORY;
+ data->contexts = (void **)UA_calloc(request->itemsToCreateSize, sizeof(void *));
+ if(!data->contexts)
+ goto cleanup;
+ if(contexts)
+ memcpy(data->contexts, contexts, request->itemsToCreateSize * sizeof(void *));
+
+ data->deleteCallbacks = (UA_Client_DeleteMonitoredItemCallback *)
+ UA_calloc(request->itemsToCreateSize, sizeof(UA_Client_DeleteMonitoredItemCallback));
+ if(!data->deleteCallbacks)
+ goto cleanup;
+ if(deleteCallbacks)
+ memcpy(data->deleteCallbacks, deleteCallbacks,
+ request->itemsToCreateSize * sizeof(UA_Client_DeleteMonitoredItemCallback));
+
+ data->handlingCallbacks = (void **)
+ UA_calloc(request->itemsToCreateSize, sizeof(void *));
+ if(!data->handlingCallbacks)
+ goto cleanup;
+ if(handlingCallbacks)
+ memcpy(data->handlingCallbacks, handlingCallbacks,
+ request->itemsToCreateSize * sizeof(void *));
+
+ retval = UA_CreateMonitoredItemsRequest_copy(request, &data->request);
+ if(retval != UA_STATUSCODE_GOOD)
+ goto cleanup;
/* Set the clientHandle */
- for(size_t i = 0; i < data->request->itemsToCreateSize; i++)
- data->request->itemsToCreate[i].requestedParameters.clientHandle =
- ++(client->monitoredItemHandles);
+ for(size_t i = 0; i < data->request.itemsToCreateSize; i++)
+ data->request.itemsToCreate[i].requestedParameters.clientHandle =
+ ++client->monitoredItemHandles;
return UA_STATUSCODE_GOOD;
+
+cleanup:
+ MonitoredItems_CreateData_clear(client, data);
+ return retval;
}
static void
-__UA_Client_MonitoredItems_create(UA_Client *client,
- const UA_CreateMonitoredItemsRequest *request,
- void **contexts, void **handlingCallbacks,
- UA_Client_DeleteMonitoredItemCallback *deleteCallbacks,
- UA_CreateMonitoredItemsResponse *response) {
+ua_Client_MonitoredItems_create(UA_Client *client,
+ const UA_CreateMonitoredItemsRequest *request,
+ void **contexts, void **handlingCallbacks,
+ UA_Client_DeleteMonitoredItemCallback *deleteCallbacks,
+ UA_CreateMonitoredItemsResponse *response) {
UA_CreateMonitoredItemsResponse_init(response);
if(!request->itemsToCreateSize) {
@@ -45202,125 +49305,63 @@ __UA_Client_MonitoredItems_create(UA_Client *client,
return;
}
- /* Get the subscription */
+ /* Test if the subscription is valid */
UA_Client_Subscription *sub = findSubscription(client, request->subscriptionId);
if(!sub) {
response->responseHeader.serviceResult = UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
return;
}
- size_t itemsToCreateSize = request->itemsToCreateSize;
- UA_STACKARRAY(UA_Client_MonitoredItem *, mis, itemsToCreateSize);
- memset(mis, 0, sizeof(void *) * itemsToCreateSize);
-
MonitoredItems_CreateData data;
memset(&data, 0, sizeof(MonitoredItems_CreateData));
- data.request = (UA_CreateMonitoredItemsRequest *)(uintptr_t)request;
- data.contexts = contexts;
- data.handlingCallbacks = handlingCallbacks;
- data.deleteCallbacks = deleteCallbacks;
- data.mis = mis;
- data.sub = sub;
-
- CustomCallback cc;
- memset(&cc, 0, sizeof(CustomCallback));
-#ifdef __clang_analyzer__
- cc.isAsync = false;
-#endif
- cc.clientData = &data;
- UA_StatusCode retval = MonitoredItems_CreateData_prepare(mis, &data, client);
- if(retval != UA_STATUSCODE_GOOD) {
- response->responseHeader.serviceResult = retval;
- MonitoredItems_CreateData_deleteItems(mis, &data, client);
+ UA_StatusCode res =
+ MonitoredItems_CreateData_prepare(client, request, contexts, handlingCallbacks,
+ deleteCallbacks, &data);
+ if(res != UA_STATUSCODE_GOOD) {
+ response->responseHeader.serviceResult = res;
return;
}
- /* Call the service */
- __UA_Client_Service(client, request, &UA_TYPES[UA_TYPES_CREATEMONITOREDITEMSREQUEST],
+ /* Call the service. Use data->request as it contains the client handle
+ * information. */
+ __UA_Client_Service(client, &data.request,
+ &UA_TYPES[UA_TYPES_CREATEMONITOREDITEMSREQUEST],
response, &UA_TYPES[UA_TYPES_CREATEMONITOREDITEMSRESPONSE]);
- __MonitoredItems_create_handler(client, &cc, 0, response);
- MonitoredItems_CreateData_deleteItems(mis, &data, client);
+ /* Add internal representation */
+ ua_MonitoredItems_create(client, &data, response);
- for(size_t i = 0; i < itemsToCreateSize; i++)
- UA_assert(mis[i] == NULL);
+ MonitoredItems_CreateData_clear(client, &data);
}
static UA_StatusCode
-__UA_Client_MonitoredItems_createDataChanges_async(UA_Client *client,
- const UA_CreateMonitoredItemsRequest request,
- void **contexts, void **callbacks,
- UA_Client_DeleteMonitoredItemCallback *deleteCallbacks,
- UA_ClientAsyncServiceCallback createCallback,
- void *userdata, UA_UInt32 *requestId) {
+ua_Client_MonitoredItems_createDataChanges_async(
+ UA_Client *client, const UA_CreateMonitoredItemsRequest request, void **contexts,
+ void **callbacks, UA_Client_DeleteMonitoredItemCallback *deleteCallbacks,
+ UA_ClientAsyncServiceCallback createCallback, void *userdata, UA_UInt32 *requestId) {
UA_Client_Subscription *sub = findSubscription(client, request.subscriptionId);
if(!sub)
return UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
- CustomCallback *cc = (CustomCallback *)UA_calloc(1, sizeof(CustomCallback));
- if(!cc)
- return UA_STATUSCODE_BADOUTOFMEMORY;
-
MonitoredItems_CreateData *data = (MonitoredItems_CreateData *)
UA_calloc(1, sizeof(MonitoredItems_CreateData));
- if(!data) {
- UA_free(cc);
+ if(!data)
return UA_STATUSCODE_BADOUTOFMEMORY;
- }
+ data->userCallback = createCallback;
+ data->userData = userdata;
- data->sub = sub;
- cc->userCallback = createCallback;
- cc->userData = userdata;
- cc->isAsync = true;
- cc->clientData = data;
-
- /* Create a big array that holds the monitored items and parameters */
- UA_StatusCode retval = UA_STATUSCODE_GOOD;
- void **array = (void **)UA_calloc(4 * request.itemsToCreateSize, sizeof(void *));
- if(!array) {
- retval = UA_STATUSCODE_BADOUTOFMEMORY;
- goto cleanup;
- }
- data->mis = (UA_Client_MonitoredItem **)array;
- data->contexts = (void **)
- ((uintptr_t)array + (sizeof(void *) * request.itemsToCreateSize));
- memcpy(data->contexts, contexts, request.itemsToCreateSize * sizeof(void *));
- data->deleteCallbacks = (UA_Client_DeleteMonitoredItemCallback *)
- ((uintptr_t)array + (2 * request.itemsToCreateSize * sizeof(void *)));
- memcpy(data->deleteCallbacks, deleteCallbacks,
- request.itemsToCreateSize * sizeof(UA_Client_DeleteMonitoredItemCallback));
- data->handlingCallbacks = (void **)
- ((uintptr_t)array + (3 * request.itemsToCreateSize * sizeof(void *)));
- memcpy(data->handlingCallbacks, callbacks, request.itemsToCreateSize * sizeof(void *));
-
- data->request = UA_CreateMonitoredItemsRequest_new();
- if(!data->request) {
- retval = UA_STATUSCODE_BADOUTOFMEMORY;
- goto cleanup;
+ UA_StatusCode res = MonitoredItems_CreateData_prepare(
+ client, &request, contexts, callbacks, deleteCallbacks, data);
+ if(res != UA_STATUSCODE_GOOD) {
+ UA_free(data);
+ return res;
}
- retval = UA_CreateMonitoredItemsRequest_copy(&request, data->request);
- if(retval != UA_STATUSCODE_GOOD)
- goto cleanup;
-
- retval = MonitoredItems_CreateData_prepare(data->mis, data, client);
- if(retval != UA_STATUSCODE_GOOD)
- goto cleanup;
- return __UA_Client_AsyncService(client, data->request,
- &UA_TYPES[UA_TYPES_CREATEMONITOREDITEMSREQUEST],
- __MonitoredItems_create_async_handler,
- &UA_TYPES[UA_TYPES_CREATEMONITOREDITEMSRESPONSE],
- cc, requestId);
-cleanup:
- MonitoredItems_CreateData_deleteItems(data->mis, data, client);
- if(data->mis)
- UA_free(data->mis);
- if(data->request)
- UA_CreateMonitoredItemsRequest_delete(data->request);
- UA_free(data);
- UA_free(cc);
- return retval;
+ return __UA_Client_AsyncService(
+ client, &data->request, &UA_TYPES[UA_TYPES_CREATEMONITOREDITEMSREQUEST],
+ ua_MonitoredItems_create_async_handler,
+ &UA_TYPES[UA_TYPES_CREATEMONITOREDITEMSRESPONSE], data, requestId);
}
UA_CreateMonitoredItemsResponse
@@ -45330,8 +49371,8 @@ UA_Client_MonitoredItems_createDataChanges(UA_Client *client,
UA_Client_DataChangeNotificationCallback *callbacks,
UA_Client_DeleteMonitoredItemCallback *deleteCallbacks) {
UA_CreateMonitoredItemsResponse response;
- __UA_Client_MonitoredItems_create(client, &request, contexts,
- (void**)(uintptr_t)callbacks, deleteCallbacks, &response);
+ ua_Client_MonitoredItems_create(client, &request, contexts, (void **)callbacks,
+ deleteCallbacks, &response);
return response;
}
@@ -45343,16 +49384,16 @@ UA_Client_MonitoredItems_createDataChanges_async(UA_Client *client,
UA_Client_DeleteMonitoredItemCallback *deleteCallbacks,
UA_ClientAsyncServiceCallback createCallback,
void *userdata, UA_UInt32 *requestId) {
- return __UA_Client_MonitoredItems_createDataChanges_async(client, request, contexts,
- (void **)(uintptr_t)callbacks,
- deleteCallbacks, createCallback,
- userdata, requestId);
+ return ua_Client_MonitoredItems_createDataChanges_async(
+ client, request, contexts, (void **)callbacks, deleteCallbacks, createCallback,
+ userdata, requestId);
}
UA_MonitoredItemCreateResult
UA_Client_MonitoredItems_createDataChange(UA_Client *client, UA_UInt32 subscriptionId,
UA_TimestampsToReturn timestampsToReturn,
- const UA_MonitoredItemCreateRequest item, void *context,
+ const UA_MonitoredItemCreateRequest item,
+ void *context,
UA_Client_DataChangeNotificationCallback callback,
UA_Client_DeleteMonitoredItemCallback deleteCallback) {
UA_CreateMonitoredItemsRequest request;
@@ -45375,17 +49416,19 @@ UA_Client_MonitoredItems_createDataChange(UA_Client *client, UA_UInt32 subscript
if(result.statusCode == UA_STATUSCODE_GOOD)
UA_MonitoredItemCreateResult_copy(&response.results[0] , &result);
- UA_CreateMonitoredItemsResponse_deleteMembers(&response);
+ UA_CreateMonitoredItemsResponse_clear(&response);
return result;
}
UA_CreateMonitoredItemsResponse
-UA_Client_MonitoredItems_createEvents(UA_Client *client, const UA_CreateMonitoredItemsRequest request,
- void **contexts, UA_Client_EventNotificationCallback *callback,
+UA_Client_MonitoredItems_createEvents(UA_Client *client,
+ const UA_CreateMonitoredItemsRequest request,
+ void **contexts,
+ UA_Client_EventNotificationCallback *callback,
UA_Client_DeleteMonitoredItemCallback *deleteCallback) {
UA_CreateMonitoredItemsResponse response;
- __UA_Client_MonitoredItems_create(client, &request, contexts,
- (void**)(uintptr_t)callback, deleteCallback, &response);
+ ua_Client_MonitoredItems_create(client, &request, contexts, (void **)callback,
+ deleteCallback, &response);
return response;
}
@@ -45398,10 +49441,9 @@ UA_Client_MonitoredItems_createEvents_async(UA_Client *client,
UA_Client_DeleteMonitoredItemCallback *deleteCallbacks,
UA_ClientAsyncServiceCallback createCallback,
void *userdata, UA_UInt32 *requestId) {
- return __UA_Client_MonitoredItems_createDataChanges_async(client, request, contexts,
- (void **)(uintptr_t)callbacks,
- deleteCallbacks, createCallback,
- userdata, requestId);
+ return ua_Client_MonitoredItems_createDataChanges_async(
+ client, request, contexts, (void **)callbacks, deleteCallbacks, createCallback,
+ userdata, requestId);
}
UA_MonitoredItemCreateResult
@@ -45423,31 +49465,22 @@ UA_Client_MonitoredItems_createEvent(UA_Client *client, UA_UInt32 subscriptionId
UA_MonitoredItemCreateResult result;
UA_MonitoredItemCreateResult_init(&result);
if(retval != UA_STATUSCODE_GOOD) {
- UA_CreateMonitoredItemsResponse_deleteMembers(&response);
+ UA_CreateMonitoredItemsResponse_clear(&response);
result.statusCode = retval;
return result;
}
UA_MonitoredItemCreateResult_copy(response.results , &result);
- UA_CreateMonitoredItemsResponse_deleteMembers(&response);
+ UA_CreateMonitoredItemsResponse_clear(&response);
return result;
}
static void
-__MonitoredItems_delete_handler(UA_Client *client, void *d, UA_UInt32 requestId, void *r) {
- UA_DeleteMonitoredItemsResponse *response = (UA_DeleteMonitoredItemsResponse *)r;
- CustomCallback *cc = (CustomCallback *)d;
- UA_DeleteMonitoredItemsRequest *request =
- (UA_DeleteMonitoredItemsRequest *)cc->clientData;
- if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD)
- goto cleanup;
-
- UA_Client_Subscription *sub = findSubscription(client, request->subscriptionId);
- if(!sub) {
- UA_LOG_INFO(&client->config.logger, UA_LOGCATEGORY_CLIENT,
- "No internal representation of subscription %" PRIu32,
- request->subscriptionId);
- goto cleanup;
- }
+ua_MonitoredItems_delete(UA_Client *client, UA_Client_Subscription *sub,
+ const UA_DeleteMonitoredItemsRequest *request,
+ const UA_DeleteMonitoredItemsResponse *response) {
+#ifdef __clang_analyzer__
+ return;
+#endif
/* Loop over deleted MonitoredItems */
for(size_t i = 0; i < response->resultsSize; i++) {
@@ -45456,25 +49489,43 @@ __MonitoredItems_delete_handler(UA_Client *client, void *d, UA_UInt32 requestId,
continue;
}
-#ifndef __clang_analyzer__
/* Delete the internal representation */
UA_Client_MonitoredItem *mon;
LIST_FOREACH(mon, &sub->monitoredItems, listEntry) {
- // NOLINTNEXTLINE
if(mon->monitoredItemId == request->monitoredItemIds[i]) {
- UA_Client_MonitoredItem_remove(client, sub, mon);
+ MonitoredItem_delete(client, sub, mon);
break;
}
}
-#endif
}
-cleanup:
- if(cc->isAsync) {
- if(cc->userCallback)
- cc->userCallback(client, cc->userData, requestId, response);
- UA_DeleteMonitoredItemsRequest_delete(request);
- UA_free(cc);
+}
+
+static void
+ua_MonitoredItems_delete_handler(UA_Client *client, void *d, UA_UInt32 requestId,
+ void *r) {
+ CustomCallback *cc = (CustomCallback *)d;
+ UA_DeleteMonitoredItemsResponse *response = (UA_DeleteMonitoredItemsResponse *)r;
+ UA_DeleteMonitoredItemsRequest *request =
+ (UA_DeleteMonitoredItemsRequest *)cc->clientData;
+ if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD)
+ goto cleanup;
+
+ UA_Client_Subscription *sub = findSubscription(client, request->subscriptionId);
+ if(!sub) {
+ UA_LOG_INFO(&client->config.logger, UA_LOGCATEGORY_CLIENT,
+ "No internal representation of subscription %" PRIu32,
+ request->subscriptionId);
+ goto cleanup;
}
+
+ /* Delete MonitoredItems from the internal representation */
+ ua_MonitoredItems_delete(client, sub, request, response);
+
+cleanup:
+ if(cc->userCallback)
+ cc->userCallback(client, cc->userData, requestId, response);
+ UA_DeleteMonitoredItemsRequest_delete(request);
+ UA_free(cc);
}
UA_DeleteMonitoredItemsResponse
@@ -45482,17 +49533,24 @@ UA_Client_MonitoredItems_delete(UA_Client *client,
const UA_DeleteMonitoredItemsRequest request) {
/* Send the request */
UA_DeleteMonitoredItemsResponse response;
- CustomCallback cc;
- memset(&cc, 0, sizeof(CustomCallback));
-#ifdef __clang_analyzer__
- cc.isAsync = false;
-#endif
- cc.clientData = (void *)(uintptr_t)&request;
-
__UA_Client_Service(client, &request, &UA_TYPES[UA_TYPES_DELETEMONITOREDITEMSREQUEST],
&response, &UA_TYPES[UA_TYPES_DELETEMONITOREDITEMSRESPONSE]);
- __MonitoredItems_delete_handler(client, &cc, 0, &response);
+ /* A problem occured remote? */
+ if(response.responseHeader.serviceResult != UA_STATUSCODE_GOOD)
+ return response;
+
+ /* Find the internal subscription representation */
+ UA_Client_Subscription *sub = findSubscription(client, request.subscriptionId);
+ if(!sub) {
+ UA_LOG_INFO(&client->config.logger, UA_LOGCATEGORY_CLIENT,
+ "No internal representation of subscription %" PRIu32,
+ request.subscriptionId);
+ return response;
+ }
+
+ /* Remove MonitoredItems in the internal representation */
+ ua_MonitoredItems_delete(client, sub, &request, &response);
return response;
}
@@ -45511,16 +49569,16 @@ UA_Client_MonitoredItems_delete_async(UA_Client *client,
UA_free(cc);
return UA_STATUSCODE_BADOUTOFMEMORY;
}
+
UA_DeleteMonitoredItemsRequest_copy(&request, req_copy);
- cc->isAsync = true;
cc->clientData = req_copy;
cc->userCallback = callback;
cc->userData = userdata;
return __UA_Client_AsyncService(
client, &request, &UA_TYPES[UA_TYPES_DELETEMONITOREDITEMSREQUEST],
- __MonitoredItems_delete_handler, &UA_TYPES[UA_TYPES_DELETEMONITOREDITEMSRESPONSE],
- cc, requestId);
+ ua_MonitoredItems_delete_handler,
+ &UA_TYPES[UA_TYPES_DELETEMONITOREDITEMSRESPONSE], cc, requestId);
}
UA_StatusCode
@@ -45537,17 +49595,17 @@ UA_Client_MonitoredItems_deleteSingle(UA_Client *client, UA_UInt32 subscriptionI
UA_StatusCode retval = response.responseHeader.serviceResult;
if(retval != UA_STATUSCODE_GOOD) {
- UA_DeleteMonitoredItemsResponse_deleteMembers(&response);
+ UA_DeleteMonitoredItemsResponse_clear(&response);
return retval;
}
if(response.resultsSize != 1) {
- UA_DeleteMonitoredItemsResponse_deleteMembers(&response);
+ UA_DeleteMonitoredItemsResponse_clear(&response);
return UA_STATUSCODE_BADINTERNALERROR;
}
retval = response.results[0];
- UA_DeleteMonitoredItemsResponse_deleteMembers(&response);
+ UA_DeleteMonitoredItemsResponse_clear(&response);
return retval;
}
@@ -45556,7 +49614,7 @@ UA_Client_MonitoredItems_modify(UA_Client *client,
const UA_ModifyMonitoredItemsRequest request) {
UA_ModifyMonitoredItemsResponse response;
- UA_Client_Subscription *sub = 0;
+ UA_Client_Subscription *sub;
LIST_FOREACH(sub, &client->subscriptions, listEntry) {
if (sub->subscriptionId == request.subscriptionId)
break;
@@ -45572,7 +49630,7 @@ UA_Client_MonitoredItems_modify(UA_Client *client,
UA_ModifyMonitoredItemsRequest_copy(&request, &modifiedRequest);
for (size_t i = 0; i < modifiedRequest.itemsToModifySize; ++i) {
- UA_Client_MonitoredItem *mon = 0;
+ UA_Client_MonitoredItem *mon;
LIST_FOREACH(mon, &sub->monitoredItems, listEntry) {
if(mon->monitoredItemId == modifiedRequest.itemsToModify[i].monitoredItemId) {
modifiedRequest.itemsToModify[i].requestedParameters.clientHandle = mon->clientHandle;
@@ -45585,7 +49643,7 @@ UA_Client_MonitoredItems_modify(UA_Client *client,
&modifiedRequest, &UA_TYPES[UA_TYPES_MODIFYMONITOREDITEMSREQUEST],
&response, &UA_TYPES[UA_TYPES_MODIFYMONITOREDITEMSRESPONSE]);
- UA_ModifyMonitoredItemsRequest_deleteMembers(&modifiedRequest);
+ UA_ModifyMonitoredItemsRequest_clear(&modifiedRequest);
return response;
}
@@ -45646,22 +49704,24 @@ processDataChangeNotification(UA_Client *client, UA_Client_Subscription *sub,
}
if(!mon) {
- UA_LOG_DEBUG(&client->config.logger, UA_LOGCATEGORY_CLIENT,
- "Could not process a notification with clienthandle %" PRIu32
- " on subscription %" PRIu32, min->clientHandle, sub->subscriptionId);
+ UA_LOG_WARNING(&client->config.logger, UA_LOGCATEGORY_CLIENT,
+ "Could not process a notification with clienthandle %" PRIu32
+ " on subscription %" PRIu32, min->clientHandle, sub->subscriptionId);
continue;
}
if(mon->isEventMonitoredItem) {
- UA_LOG_DEBUG(&client->config.logger, UA_LOGCATEGORY_CLIENT,
- "MonitoredItem is configured for Events. But received a "
- "DataChangeNotification.");
+ UA_LOG_WARNING(&client->config.logger, UA_LOGCATEGORY_CLIENT,
+ "MonitoredItem is configured for Events. But received a "
+ "DataChangeNotification.");
continue;
}
- mon->handler.dataChangeCallback(client, sub->subscriptionId, sub->context,
- mon->monitoredItemId, mon->context,
- &min->value);
+ if(mon->handler.dataChangeCallback) {
+ mon->handler.dataChangeCallback(client, sub->subscriptionId, sub->context,
+ mon->monitoredItemId, mon->context,
+ &min->value);
+ }
}
}
@@ -45729,7 +49789,8 @@ processNotificationMessage(UA_Client *client, UA_Client_Subscription *sub,
(UA_StatusChangeNotification*)msg->content.decoded.data);
} else {
UA_LOG_WARNING(&client->config.logger, UA_LOGCATEGORY_CLIENT,
- "Dropped a StatusChangeNotification since no callback is registered");
+ "Dropped a StatusChangeNotification since no "
+ "callback is registered");
}
return;
}
@@ -45749,8 +49810,8 @@ UA_Client_Subscriptions_processPublishResponse(UA_Client *client, UA_PublishRequ
if(client->config.outStandingPublishRequests > 1) {
client->config.outStandingPublishRequests--;
UA_LOG_WARNING(&client->config.logger, UA_LOGCATEGORY_CLIENT,
- "Too many publishrequest, reduce outStandingPublishRequests to %" PRId16,
- client->config.outStandingPublishRequests);
+ "Too many publishrequest, reduce outStandingPublishRequests "
+ "to %" PRId16, client->config.outStandingPublishRequests);
} else {
UA_LOG_ERROR(&client->config.logger, UA_LOGCATEGORY_CLIENT,
"Too many publishrequest when outStandingPublishRequests = 1");
@@ -45771,7 +49832,7 @@ UA_Client_Subscriptions_processPublishResponse(UA_Client *client, UA_PublishRequ
if(client->sessionState != UA_SESSIONSTATE_ACTIVATED) {
UA_LOG_WARNING(&client->config.logger, UA_LOGCATEGORY_CLIENT,
"Received Publish Response with code %s",
- UA_StatusCode_name(response->responseHeader.serviceResult));
+ UA_StatusCode_name(response->responseHeader.serviceResult));
UA_Client_Subscription* sub = findSubscription(client, response->subscriptionId);
if (sub != NULL)
UA_Client_Subscription_deleteInternal(client, sub);
@@ -45787,8 +49848,12 @@ UA_Client_Subscriptions_processPublishResponse(UA_Client *client, UA_PublishRequ
}
if(response->responseHeader.serviceResult == UA_STATUSCODE_BADTIMEOUT) {
- if (client->config.inactivityCallback)
- client->config.inactivityCallback(client);
+ if (client->config.subscriptionInactivityCallback) {
+ UA_Client_Subscription* sub = findSubscription(client, response->subscriptionId);
+ if (sub != NULL)
+ client->config.subscriptionInactivityCallback(client, sub->subscriptionId,
+ sub->context);
+ }
UA_LOG_WARNING(&client->config.logger, UA_LOGCATEGORY_CLIENT,
"Received Timeout for Publish Response");
return;
@@ -45814,19 +49879,20 @@ UA_Client_Subscriptions_processPublishResponse(UA_Client *client, UA_PublishRequ
/* Detect missing message - OPC Unified Architecture, Part 4 5.13.1.1 e) */
if(UA_Client_Subscriptions_nextSequenceNumber(sub->sequenceNumber) != msg->sequenceNumber) {
UA_LOG_WARNING(&client->config.logger, UA_LOGCATEGORY_CLIENT,
- "Invalid subscription sequence number: expected %" PRIu32 " but got %" PRIu32,
- UA_Client_Subscriptions_nextSequenceNumber(sub->sequenceNumber),
- msg->sequenceNumber);
+ "Invalid subscription sequence number: expected %" PRIu32
+ " but got %" PRIu32,
+ UA_Client_Subscriptions_nextSequenceNumber(sub->sequenceNumber),
+ msg->sequenceNumber);
/* This is an error. But we do not abort the connection. Some server
* SDKs misbehave from time to time and send out-of-order sequence
* numbers. (Probably some multi-threading synchronization issue.) */
/* UA_Client_disconnect(client);
return; */
}
- /* According to f), a keep-alive message contains no notifications and has the sequence number
- * of the next NotificationMessage that is to be sent => More than one consecutive keep-alive
- * message or a NotificationMessage following a keep-alive message will share the same sequence
- * number. */
+ /* According to f), a keep-alive message contains no notifications and has
+ * the sequence number of the next NotificationMessage that is to be sent =>
+ * More than one consecutive keep-alive message or a NotificationMessage
+ * following a keep-alive message will share the same sequence number. */
if (msg->notificationDataSize)
sub->sequenceNumber = msg->sequenceNumber;
@@ -45854,8 +49920,8 @@ UA_Client_Subscriptions_processPublishResponse(UA_Client *client, UA_PublishRequ
}
static void
-processPublishResponseAsync(UA_Client *client, void *userdata, UA_UInt32 requestId,
- void *response) {
+processPublishResponseAsync(UA_Client *client, void *userdata,
+ UA_UInt32 requestId, void *response) {
UA_PublishRequest *req = (UA_PublishRequest*)userdata;
UA_PublishResponse *res = (UA_PublishResponse*)response;
@@ -45871,13 +49937,15 @@ processPublishResponseAsync(UA_Client *client, void *userdata, UA_UInt32 request
void
UA_Client_Subscriptions_clean(UA_Client *client) {
- UA_Client_NotificationsAckNumber *n, *tmp;
+ UA_Client_NotificationsAckNumber *n;
+ UA_Client_NotificationsAckNumber *tmp;
LIST_FOREACH_SAFE(n, &client->pendingNotificationsAcks, listEntry, tmp) {
LIST_REMOVE(n, listEntry);
UA_free(n);
}
- UA_Client_Subscription *sub, *tmps;
+ UA_Client_Subscription *sub;
+ UA_Client_Subscription *tmps;
LIST_FOREACH_SAFE(sub, &client->subscriptions, listEntry, tmps)
UA_Client_Subscription_deleteInternal(client, sub); /* force local removal */
@@ -45937,7 +50005,8 @@ UA_Client_Subscriptions_backgroundPublish(UA_Client *client) {
/* Disable the timeout, it is treat in
* UA_Client_Subscriptions_backgroundPublishInactivityCheck */
- retval = __UA_Client_AsyncServiceEx(client, request, &UA_TYPES[UA_TYPES_PUBLISHREQUEST],
+ retval = __UA_Client_AsyncServiceEx(client, request,
+ &UA_TYPES[UA_TYPES_PUBLISHREQUEST],
processPublishResponseAsync,
&UA_TYPES[UA_TYPES_PUBLISHRESPONSE],
(void*)request, &requestId, 0);
@@ -45950,7 +50019,7 @@ UA_Client_Subscriptions_backgroundPublish(UA_Client *client) {
#endif /* UA_ENABLE_SUBSCRIPTIONS */
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/deps/libc_time.c" ***********************************/
+/**** amalgamated original file "/deps/libc_time.c" ****/
/* Originally released by the musl project (http://www.musl-libc.org/) under the
* MIT license. Taken from the file /src/time/__secs_to_tm.c */
@@ -46099,7 +50168,7 @@ long long __tm_to_secs(const struct mytm *tm) {
return t;
}
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/deps/pcg_basic.c" ***********************************/
+/**** amalgamated original file "/deps/pcg_basic.c" ****/
/*
* PCG Random Number Generation for C.
@@ -46141,7 +50210,7 @@ uint32_t pcg32_random_r(pcg32_random_t* rng) {
return (xorshifted >> rot) | (xorshifted << ((~rot + 1u) & 31)); /* was (xorshifted >> rot) | (xorshifted << ((-rot) & 31)) */
}
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/deps/base64.c" ***********************************/
+/**** amalgamated original file "/deps/base64.c" ****/
/*
* Base64 encoding: Copyright (c) 2005-2011, Jouni Malinen <j@w1.fi>
@@ -46257,7 +50326,1644 @@ UA_unbase64(const unsigned char *src, size_t len, size_t *out_len) {
return str;
}
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/build/src_generated/open62541/namespace0_generated.c" ***********************************/
+/**** amalgamated original file "/deps/aa_tree.c" ****/
+
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Copyright 2020 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
+ */
+
+#include <stddef.h>
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1800
+# include <inttypes.h>
+#elif !defined(uintptr_t)
+ /* Workaround missing standard includes in older Visual Studio */
+# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300
+typedef _W64 unsigned int uintptr_t;
+# else
+typedef unsigned __int64 uintptr_t;
+# endif
+#endif
+
+#define aa_entry_container(head, entry) \
+ ((void*)((uintptr_t)entry - head->entry_offset))
+#define aa_entry_key(head, entry) \
+ ((const void*)((uintptr_t)entry + head->key_offset - head->entry_offset))
+#define aa_container_entry(head, container) \
+ ((struct aa_entry*)((uintptr_t)container + head->entry_offset))
+#define aa_container_key(head, container) \
+ ((const void*)((uintptr_t)container + head->key_offset))
+
+void
+aa_init(struct aa_head *head,
+ enum aa_cmp (*cmp)(const void*, const void*),
+ unsigned int entry_offset, unsigned int key_offset) {
+ head->root = NULL;
+ head->cmp = cmp;
+ head->entry_offset = entry_offset;
+ head->key_offset = key_offset;
+}
+
+static struct aa_entry *
+_aa_skew(struct aa_entry *n) {
+ if(!n)
+ return NULL;
+ if(n->left && n->level == n->left->level) {
+ struct aa_entry *l = n->left;
+ n->left = l->right;
+ l->right = n;
+ return l;
+ }
+ return n;
+}
+
+static struct aa_entry *
+_aa_split(struct aa_entry *n) {
+ if(!n)
+ return NULL;
+ if(n->right && n->right->right &&
+ n->right->right->level == n->level) {
+ struct aa_entry *r = n->right;
+ n->right = r->left;
+ r->left = n;
+ r->level++;
+ return r;
+ }
+ return n;
+}
+
+static struct aa_entry *
+_aa_fixup(struct aa_entry *n) {
+ unsigned int should_be = 0;
+ if(n->left)
+ should_be = n->left->level;
+ if(n->right && n->right->level < should_be)
+ should_be = n->right->level;
+ should_be++;
+ if(should_be < n->level)
+ n->level = should_be;
+ if(n->right && n->right->level > should_be)
+ n->right->level = should_be;
+ n = _aa_skew(n);
+ n->right = _aa_skew(n->right);
+ if(n->right)
+ n->right->right = _aa_skew(n->right->right);
+ n = _aa_split(n);
+ n->right = _aa_split(n->right);
+ return n;
+}
+
+static struct aa_entry *
+_aa_insert(struct aa_head *h, struct aa_entry *n, void *elem) {
+ if(!n) {
+ struct aa_entry *e = aa_container_entry(h, elem);
+ e->left = NULL;
+ e->right = NULL;
+ e->level = 1;
+ return e;
+ }
+ const void *n_key = aa_entry_key(h, n);
+ const void *key = aa_container_key(h, elem);
+ enum aa_cmp eq = h->cmp(key, n_key);
+ if(eq == AA_CMP_EQ)
+ eq = (key > n_key) ? AA_CMP_MORE : AA_CMP_LESS;
+ if(eq == AA_CMP_LESS)
+ n->left = _aa_insert(h, n->left, elem);
+ else
+ n->right = _aa_insert(h, n->right, elem);
+ return _aa_split(_aa_skew(n));
+}
+
+void
+aa_insert(struct aa_head *h, void *elem) {
+ h->root = _aa_insert(h, h->root, elem);
+}
+
+void *
+aa_find(const struct aa_head *h, const void *key) {
+ struct aa_entry *n = h->root;
+ while(n) {
+ enum aa_cmp eq = h->cmp(key, aa_entry_key(h, n));
+ if(eq == AA_CMP_EQ)
+ return aa_entry_container(h, n);
+ n = (eq == AA_CMP_LESS) ? n->left : n->right;
+ }
+ return NULL;
+}
+
+static struct aa_entry *
+unlink_succ(struct aa_entry *n, struct aa_entry **succ) {
+ if(!n->left) {
+ *succ = n;
+ return n->right;
+ }
+ n->left = unlink_succ(n->left, succ);
+ return _aa_fixup(n);
+}
+
+static struct aa_entry *
+unlink_pred(struct aa_entry *n, struct aa_entry **pred) {
+ if(!n->right) {
+ *pred = n;
+ return n->left;
+ }
+ n->right = unlink_pred(n->right, pred);
+ return _aa_fixup(n);
+}
+
+static struct aa_entry *
+_aa_remove(struct aa_head *h, void *elem, struct aa_entry *n) {
+ if(!n)
+ return NULL;
+
+ const void *elem_key = aa_container_key(h, elem);
+ const void *n_key = aa_entry_key(h, n);
+ if(n_key == elem_key) {
+ if(!n->left && !n->right)
+ return NULL;
+ struct aa_entry *replace = NULL;
+ if(!n->left)
+ n->right = unlink_succ(n->right, &replace);
+ else
+ n->left = unlink_pred(n->left, &replace);
+ replace->left = n->left;
+ replace->right = n->right;
+ replace->level = n->level;
+ return _aa_fixup(replace);
+ }
+
+ enum aa_cmp eq = h->cmp(elem_key, n_key);
+ if(eq == AA_CMP_EQ)
+ eq = (elem_key > n_key) ? AA_CMP_MORE : AA_CMP_LESS;
+ if(eq == AA_CMP_LESS)
+ n->left = _aa_remove(h, elem, n->left);
+ else
+ n->right = _aa_remove(h, elem, n->right);
+ return _aa_fixup(n);
+}
+
+void
+aa_remove(struct aa_head *head, void *elem) {
+ head->root = _aa_remove(head, elem, head->root);
+}
+
+void *
+aa_min(const struct aa_head *head) {
+ struct aa_entry *e = head->root;
+ if(!e)
+ return NULL;
+ while(e->left)
+ e = e->left;
+ return aa_entry_container(head, e);
+}
+
+void *
+aa_max(const struct aa_head *head) {
+ struct aa_entry *e = head->root;
+ if(!e)
+ return NULL;
+ while(e->right)
+ e = e->right;
+ return aa_entry_container(head, e);
+}
+
+void *
+aa_next(const struct aa_head *head, const void *elem) {
+ struct aa_entry *e = aa_container_entry(head, elem);
+ if(e->right) {
+ e = e->right;
+ while(e->left)
+ e = e->left;
+ return aa_entry_container(head, e);
+ }
+ struct aa_entry *next = NULL;
+ struct aa_entry *n = head->root;
+ const void *key = aa_container_key(head, elem);
+ while(n && n != e) {
+ const void *n_key = aa_entry_key(head, n);
+ enum aa_cmp eq = head->cmp(key, n_key);
+ if(eq == AA_CMP_EQ)
+ eq = (key > n_key) ? AA_CMP_MORE : AA_CMP_LESS;
+ if(eq == AA_CMP_MORE) {
+ n = n->right;
+ } else {
+ next = n;
+ n = n->left;
+ }
+ }
+ return (next) ? aa_entry_container(head, next) : NULL;
+}
+
+void *
+aa_prev(const struct aa_head *head, const void *elem) {
+ struct aa_entry *e = aa_container_entry(head, elem);
+ if(e->left) {
+ e = e->left;
+ while(e->right)
+ e = e->right;
+ return aa_entry_container(head, e);
+ }
+ struct aa_entry *prev = NULL;
+ struct aa_entry *n = head->root;
+ const void *key = aa_container_key(head, elem);
+ while(n && n != e) {
+ const void *n_key = aa_entry_key(head, n);
+ enum aa_cmp eq = head->cmp(key, n_key);
+ if(eq == AA_CMP_EQ)
+ eq = (key > n_key) ? AA_CMP_MORE : AA_CMP_LESS;
+ if(eq == AA_CMP_MORE) {
+ prev = n;
+ n = n->right;
+ } else {
+ n = n->left;
+ }
+ }
+ return (prev) ? aa_entry_container(head, prev) : NULL;
+}
+
+/**** amalgamated original file "/deps/ziptree.c" ****/
+
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Copyright 2021 (c) Julius Pfrommer
+ */
+
+
+#if defined(_MSC_VER)
+#include <intrin.h>
+#endif
+
+unsigned char
+__ZIP_FFS32(unsigned int v) {
+#if defined(__GNUC__) || defined(__clang__)
+ return (unsigned char)((unsigned char)__builtin_ffs((int)v) - 1u);
+#elif defined(_MSC_VER)
+ unsigned long index = 255;
+ _BitScanForward(&index, v);
+ return (unsigned char)index;
+#else
+ if(v == 0)
+ return 255;
+ unsigned int t = 1;
+ unsigned char r = 0;
+ while((v & t) == 0) {
+ t = t << 1;
+ r++;
+ }
+ return r;
+#endif
+}
+
+/* Generic analog to ZIP_ENTRY(type) */
+struct zip_entry {
+ void *left;
+ void *right;
+ unsigned char rank;
+};
+
+#define ZIP_ENTRY_PTR(x) (struct zip_entry*)((char*)x + fieldoffset)
+#define ZIP_KEY_PTR(x) (void*)((char*)x + keyoffset)
+
+void *
+__ZIP_INSERT(zip_cmp_cb cmp, unsigned short fieldoffset,
+ unsigned short keyoffset, void *root, void *elm) {
+ struct zip_entry *root_entry = ZIP_ENTRY_PTR(root);
+ struct zip_entry *elm_entry = ZIP_ENTRY_PTR(elm);
+ if(!root) {
+ elm_entry->left = NULL;
+ elm_entry->right = NULL;
+ return elm;
+ }
+ enum ZIP_CMP order = cmp(ZIP_KEY_PTR(elm), ZIP_KEY_PTR(root));
+ if(order == ZIP_CMP_LESS) {
+ if(__ZIP_INSERT(cmp, fieldoffset, keyoffset, root_entry->left, elm) == elm) {
+ if(elm_entry->rank < root_entry->rank) {
+ root_entry->left = elm;
+ } else {
+ root_entry->left = elm_entry->right;
+ elm_entry->right = root;
+ return elm;
+ }
+ }
+ } else {
+ if(__ZIP_INSERT(cmp, fieldoffset, keyoffset, root_entry->right, elm) == elm) {
+ if(elm_entry->rank <= root_entry->rank) {
+ root_entry->right = elm;
+ } else {
+ root_entry->right = elm_entry->left;
+ elm_entry->left = root;
+ return elm;
+ }
+ }
+ }
+ return root;
+}
+
+static void *
+__ZIP(unsigned short fieldoffset, void *x, void *y) {
+ if(!x) return y;
+ if(!y) return x;
+ struct zip_entry *x_entry = ZIP_ENTRY_PTR(x);
+ struct zip_entry *y_entry = ZIP_ENTRY_PTR(y);
+ if(x_entry->rank < y_entry->rank) {
+ y_entry->left = __ZIP(fieldoffset, x, y_entry->left);
+ return y;
+ } else {
+ x_entry->right = __ZIP(fieldoffset, x_entry->right, y);
+ return x;
+ }
+}
+
+/* Modified from the original algorithm. Allow multiple elements with the same
+ * key. */
+void *
+__ZIP_REMOVE(zip_cmp_cb cmp, unsigned short fieldoffset,
+ unsigned short keyoffset, void *root, void *elm) {
+ struct zip_entry *root_entry = ZIP_ENTRY_PTR(root);
+ if(root == elm)
+ return __ZIP(fieldoffset, root_entry->left, root_entry->right);
+ void *left = root_entry->left;
+ void *right = root_entry->right;
+ enum ZIP_CMP eq = cmp(ZIP_KEY_PTR(elm), ZIP_KEY_PTR(root));
+ if(eq == ZIP_CMP_LESS) {
+ struct zip_entry *left_entry = ZIP_ENTRY_PTR(left);
+ if(elm == left)
+ root_entry->left = __ZIP(fieldoffset, left_entry->left, left_entry->right);
+ else if(left)
+ __ZIP_REMOVE(cmp, fieldoffset, keyoffset, left, elm);
+ } else if(eq == ZIP_CMP_MORE) {
+ struct zip_entry *right_entry = ZIP_ENTRY_PTR(right);
+ if(elm == right)
+ root_entry->right = __ZIP(fieldoffset, right_entry->left, right_entry->right);
+ else if(right)
+ __ZIP_REMOVE(cmp, fieldoffset, keyoffset, right, elm);
+ } else { /* ZIP_CMP_EQ, but root != elm */
+ if(right)
+ root_entry->right = __ZIP_REMOVE(cmp, fieldoffset, keyoffset, right, elm);
+ if(left)
+ root_entry->left = __ZIP_REMOVE(cmp, fieldoffset, keyoffset, left, elm);
+ }
+ return root;
+}
+
+void *
+__ZIP_FIND(zip_cmp_cb cmp, unsigned short fieldoffset,
+ unsigned short keyoffset, void *root, const void *key) {
+ if(!root)
+ return NULL;
+ enum ZIP_CMP eq = cmp(key, ZIP_KEY_PTR(root));
+ if(eq == ZIP_CMP_EQ)
+ return root;
+ struct zip_entry *root_entry = ZIP_ENTRY_PTR(root);
+ if(eq == ZIP_CMP_LESS)
+ return __ZIP_FIND(cmp, fieldoffset, keyoffset, root_entry->left, key);
+ else
+ return __ZIP_FIND(cmp, fieldoffset, keyoffset, root_entry->right, key);
+}
+
+void *
+__ZIP_MIN(unsigned short fieldoffset, void *elm) {
+ if(!elm)
+ return NULL;
+ struct zip_entry *elm_entry = ZIP_ENTRY_PTR(elm);
+ while(elm_entry->left) {
+ elm = elm_entry->left;
+ elm_entry = (struct zip_entry*)((char*)elm + fieldoffset);
+ }
+ return elm;
+}
+
+void *
+__ZIP_MAX(unsigned short fieldoffset, void *elm) {
+ if(!elm)
+ return NULL;
+ struct zip_entry *elm_entry = ZIP_ENTRY_PTR(elm);
+ while(elm_entry->right) {
+ elm = elm_entry->right;
+ elm_entry = (struct zip_entry*)((char*)elm + fieldoffset);
+ }
+ return elm;
+}
+
+void
+__ZIP_ITER(unsigned short fieldoffset, __zip_iter_cb cb,
+ void *context, void *elm) {
+ if(!elm)
+ return;
+ struct zip_entry *elm_entry = ZIP_ENTRY_PTR(elm);
+ __ZIP_ITER(fieldoffset, cb, context, elm_entry->left);
+ __ZIP_ITER(fieldoffset, cb, context, elm_entry->right);
+ cb(elm, context);
+}
+
+/**** amalgamated original file "/src/pubsub/ua_pubsub_config.c" ****/
+
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Copyright (c) 2020 Yannick Wallerer, Siemens AG
+ * Copyright (c) 2020 Thomas Fischer, Siemens AG
+ */
+
+
+#ifdef UA_ENABLE_PUBSUB
+#ifdef UA_ENABLE_PUBSUB_ETH_UADP
+#endif
+#endif
+
+
+#ifdef UA_ENABLE_PUBSUB_FILE_CONFIG
+
+static UA_StatusCode
+createPubSubConnection(UA_Server *server,
+ const UA_PubSubConnectionDataType *connection,
+ UA_UInt32 pdsCount, UA_NodeId *pdsIdent);
+
+static UA_StatusCode
+createWriterGroup(UA_Server *server,
+ const UA_WriterGroupDataType *writerGroupParameters,
+ UA_NodeId connectionIdent, UA_UInt32 pdsCount,
+ const UA_NodeId *pdsIdent);
+
+static UA_StatusCode
+createDataSetWriter(UA_Server *server,
+ const UA_DataSetWriterDataType *dataSetWriterParameters,
+ UA_NodeId writerGroupIdent, UA_UInt32 pdsCount,
+ const UA_NodeId *pdsIdent);
+
+static UA_StatusCode
+createReaderGroup(UA_Server *server,
+ const UA_ReaderGroupDataType *readerGroupParameters,
+ UA_NodeId connectionIdent);
+
+static UA_StatusCode
+createDataSetReader(UA_Server *server,
+ const UA_DataSetReaderDataType *dataSetReaderParameters,
+ UA_NodeId readerGroupIdent);
+
+static UA_StatusCode
+createPublishedDataSet(UA_Server *server,
+ const UA_PublishedDataSetDataType *publishedDataSetParameters,
+ UA_NodeId *publishedDataSetIdent);
+
+static UA_StatusCode
+createDataSetFields(UA_Server *server,
+ const UA_NodeId *publishedDataSetIdent,
+ const UA_PublishedDataSetDataType *publishedDataSetParameters);
+
+static UA_StatusCode
+generatePubSubConfigurationDataType(const UA_Server *server,
+ UA_PubSubConfigurationDataType *pubSubConfiguration);
+
+/* Gets PubSub Configuration from an ExtensionObject */
+static UA_StatusCode
+extractPubSubConfigFromExtensionObject(const UA_ExtensionObject *src,
+ UA_PubSubConfigurationDataType **dst) {
+ if(src->encoding != UA_EXTENSIONOBJECT_DECODED ||
+ src->content.decoded.type != &UA_TYPES[UA_TYPES_UABINARYFILEDATATYPE]) {
+ UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
+ "[UA_PubSubManager_extractPubSubConfigFromDecodedObject] "
+ "Reading extensionObject failed");
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+ }
+
+ UA_UABinaryFileDataType *binFile = (UA_UABinaryFileDataType*)src->content.decoded.data;
+
+ if(binFile->body.arrayLength != 0 || binFile->body.arrayDimensionsSize != 0) {
+ UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
+ "[UA_PubSubManager_extractPubSubConfigFromDecodedObject] "
+ "Loading multiple configurations is not supported");
+ return UA_STATUSCODE_BADNOTIMPLEMENTED;
+ }
+
+ if(binFile->body.type != &UA_TYPES[UA_TYPES_PUBSUBCONFIGURATIONDATATYPE]) {
+ UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
+ "[UA_PubSubManager_extractPubSubConfigFromDecodedObject] "
+ "Invalid datatype encoded in the binary file");
+ return UA_STATUSCODE_BADTYPEMISMATCH;
+ }
+
+ *dst = (UA_PubSubConfigurationDataType*)binFile->body.data;
+ return UA_STATUSCODE_GOOD;
+}
+
+/* Configures a PubSub Server with given PubSubConfigurationDataType object */
+static UA_StatusCode
+updatePubSubConfig(UA_Server *server,
+ const UA_PubSubConfigurationDataType *configurationParameters) {
+ if(server == NULL || configurationParameters == NULL) {
+ UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
+ "[UA_PubSubManager_updatePubSubConfig] Invalid argument");
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+ }
+
+ UA_PubSubManager_delete(server, &server->pubSubManager);
+
+ /* Configuration of Published DataSets: */
+ UA_UInt32 pdsCount = (UA_UInt32)configurationParameters->publishedDataSetsSize;
+ UA_NodeId *publishedDataSetIdent = (UA_NodeId*)UA_calloc(pdsCount, sizeof(UA_NodeId));
+ if(!publishedDataSetIdent)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+
+ UA_StatusCode res = UA_STATUSCODE_GOOD;
+ for(UA_UInt32 i = 0; i < pdsCount; i++) {
+ res = createPublishedDataSet(server,
+ &configurationParameters->publishedDataSets[i],
+ &publishedDataSetIdent[i]);
+ if(res != UA_STATUSCODE_GOOD) {
+ UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
+ "[UA_PubSubManager_updatePubSubConfig] PDS creation failed");
+ UA_free(publishedDataSetIdent);
+ return res;
+ }
+ }
+
+ /* Configuration of PubSub Connections: */
+ if(configurationParameters->connectionsSize < 1) {
+ UA_LOG_WARNING(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
+ "[UA_PubSubManager_updatePubSubConfig] no connection in "
+ "UA_PubSubConfigurationDataType");
+ UA_free(publishedDataSetIdent);
+ return UA_STATUSCODE_GOOD;
+ }
+
+ for(size_t i = 0; i < configurationParameters->connectionsSize; i++) {
+ res = createPubSubConnection(server,
+ &configurationParameters->connections[i],
+ pdsCount, publishedDataSetIdent);
+ if(res != UA_STATUSCODE_GOOD)
+ break;
+ }
+
+ UA_free(publishedDataSetIdent);
+ return res;
+}
+
+/* Function called by UA_PubSubManager_createPubSubConnection to set the
+ * PublisherId of a certain connection. */
+static UA_StatusCode
+setConnectionPublisherId(const UA_PubSubConnectionDataType *src,
+ UA_PubSubConnectionConfig *dst) {
+ if(src->publisherId.type == &UA_TYPES[UA_TYPES_STRING]) {
+ dst->publisherIdType = UA_PUBSUB_PUBLISHERID_STRING;
+ dst->publisherId.string = *(UA_String*)src->publisherId.data;
+ } else if(src->publisherId.type == &UA_TYPES[UA_TYPES_BYTE] ||
+ src->publisherId.type == &UA_TYPES[UA_TYPES_UINT16] ||
+ src->publisherId.type == &UA_TYPES[UA_TYPES_UINT32]) {
+ dst->publisherIdType = UA_PUBSUB_PUBLISHERID_NUMERIC;
+ dst->publisherId.numeric = *(UA_UInt32*)src->publisherId.data;
+ } else if(src->publisherId.type == &UA_TYPES[UA_TYPES_UINT64]) {
+ UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
+ "[UA_PubSubManager_setConnectionPublisherId] PublisherId is UInt64 "
+ "(not implemented); Recommended dataType for PublisherId: UInt32");
+ return UA_STATUSCODE_BADNOTIMPLEMENTED;
+ } else {
+ UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
+ "[UA_PubSubManager_setConnectionPublisherId] PublisherId is not valid.");
+ return UA_STATUSCODE_BADINTERNALERROR;
+ }
+ return UA_STATUSCODE_GOOD;
+}
+
+/* Function called by UA_PubSubManager_createPubSubConnection to create all WriterGroups
+ * and ReaderGroups that belong to a certain connection. */
+static UA_StatusCode
+createComponentsForConnection(UA_Server *server,
+ const UA_PubSubConnectionDataType *connParams,
+ UA_NodeId connectionIdent, UA_UInt32 pdsCount,
+ const UA_NodeId *pdsIdent) {
+ /* WriterGroups configuration */
+ UA_StatusCode res = UA_STATUSCODE_GOOD;
+ for(size_t i = 0; i < connParams->writerGroupsSize; i++) {
+ res = createWriterGroup(server, &connParams->writerGroups[i],
+ connectionIdent, pdsCount, pdsIdent);
+ if(res != UA_STATUSCODE_GOOD) {
+ UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
+ "[UA_PubSubManager_createComponentsForConnection] "
+ "Error occured during %d. WriterGroup Creation", (UA_UInt32)i+1);
+ return res;
+ }
+ }
+
+ /* ReaderGroups configuration */
+ for(size_t j = 0; j < connParams->readerGroupsSize; j++) {
+ res = createReaderGroup(server, &connParams->readerGroups[j], connectionIdent);
+ if(res == UA_STATUSCODE_GOOD)
+ res |= UA_PubSubConnection_regist(server, &connectionIdent);
+ if(res != UA_STATUSCODE_GOOD) {
+ UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
+ "[UA_PubSubManager_createComponentsForConnection] "
+ "Error occured during %d. ReaderGroup Creation", (UA_UInt32)j+1);
+ return res;
+ }
+ }
+
+ return res;
+}
+
+/* Checks if transportLayer for the specified transportProfileUri exists.
+ *
+ * @param server Server object that shall be configured
+ * @param transportProfileUri String that specifies the transport protocol */
+static UA_Boolean
+transportLayerExists(UA_Server *server, UA_String transportProfileUri) {
+ for(size_t i = 0; i < server->config.pubSubConfig.transportLayersSize; i++) {
+ if(UA_String_equal(&server->config.pubSubConfig.transportLayers[i].transportProfileUri,
+ &transportProfileUri)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+/* Creates transportlayer for specified transport protocol if this layer doesn't exist yet */
+static UA_StatusCode
+createTransportLayer(UA_Server *server, const UA_String transportProfileUri) {
+ if(transportLayerExists(server, transportProfileUri))
+ return UA_STATUSCODE_GOOD;
+
+ UA_ServerConfig *config = UA_Server_getConfig(server);
+ UA_PubSubTransportLayer tl;
+
+ do {
+ UA_String strUDP =
+ UA_STRING("http://opcfoundation.org/UA-Profile/Transport/pubsub-udp-uadp");
+ if(UA_String_equal(&transportProfileUri, &strUDP)) {
+ tl = UA_PubSubTransportLayerUDPMP();
+ break;
+ }
+
+#ifdef UA_ENABLE_PUBSUB_ETH_UADP
+ UA_String strETH =
+ UA_STRING("http://opcfoundation.org/UA-Profile/Transport/pubsub-eth-uadp");
+ if(UA_String_equal(&transportProfileUri, &strETH)) {
+ tl = UA_PubSubTransportLayerEthernet();
+ break;
+ }
+#endif
+
+ UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
+ "[UA_PubSubManager_createTransportLayer] "
+ "invalid transportProfileUri");
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+ } while(0);
+
+ if(config->pubSubConfig.transportLayersSize > 0) {
+ config->pubSubConfig.transportLayers = (UA_PubSubTransportLayer *)
+ UA_realloc(config->pubSubConfig.transportLayers,
+ (config->pubSubConfig.transportLayersSize + 1) *
+ sizeof(UA_PubSubTransportLayer));
+ } else {
+ config->pubSubConfig.transportLayers = (UA_PubSubTransportLayer *)
+ UA_calloc(1, sizeof(UA_PubSubTransportLayer));
+ }
+
+ if(config->pubSubConfig.transportLayers == NULL) {
+ UA_Server_delete(server);
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ }
+ config->pubSubConfig.transportLayers[config->pubSubConfig.transportLayersSize] = tl;
+ config->pubSubConfig.transportLayersSize++;
+ return UA_STATUSCODE_GOOD;
+}
+
+/* Creates PubSubConnection configuration from PubSubConnectionDataType object
+ *
+ * @param server Server object that shall be configured
+ * @param connParams PubSub connection configuration
+ * @param pdsCount Number of published DataSets
+ * @param pdsIdent Array of NodeIds of the published DataSets */
+static UA_StatusCode
+createPubSubConnection(UA_Server *server, const UA_PubSubConnectionDataType *connParams,
+ UA_UInt32 pdsCount, UA_NodeId *pdsIdent) {
+ UA_PubSubConnectionConfig config;
+ memset(&config, 0, sizeof(UA_PubSubConnectionConfig));
+
+ config.name = connParams->name;
+ config.enabled = connParams->enabled;
+ config.transportProfileUri = connParams->transportProfileUri;
+ config.connectionPropertiesSize = connParams->connectionPropertiesSize;
+ if(config.connectionPropertiesSize > 0) {
+ config.connectionProperties = connParams->connectionProperties;
+ }
+
+ UA_StatusCode res = setConnectionPublisherId(connParams, &config);
+ if(res != UA_STATUSCODE_GOOD) {
+ UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
+ "[UA_PubSubManager_createPubSubConnection] "
+ "Setting PublisherId failed");
+ return res;
+ }
+
+ if(connParams->address.encoding == UA_EXTENSIONOBJECT_DECODED) {
+ UA_Variant_setScalar(&(config.address),
+ connParams->address.content.decoded.data,
+ connParams->address.content.decoded.type);
+ } else {
+ UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
+ "[UA_PubSubManager_createPubSubConnection] "
+ "Reading connection address failed");
+ return UA_STATUSCODE_BADINTERNALERROR;
+ }
+
+ if(connParams->transportSettings.encoding == UA_EXTENSIONOBJECT_DECODED) {
+ UA_Variant_setScalar(&(config.connectionTransportSettings),
+ connParams->transportSettings.content.decoded.data,
+ connParams->transportSettings.content.decoded.type);
+ } else {
+ UA_LOG_WARNING(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
+ "[UA_PubSubManager_createPubSubConnection] "
+ "TransportSettings can not be read");
+ }
+
+ res = createTransportLayer(server, connParams->transportProfileUri);
+ if(res != UA_STATUSCODE_GOOD) {
+ UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
+ "[UA_PubSubManager_createPubSubConnection] "
+ "Creating transportLayer failed");
+ return res;
+ }
+
+ /* Load connection config into server: */
+ UA_NodeId connectionIdent;
+ res = UA_Server_addPubSubConnection(server, &config, &connectionIdent);
+ if(res == UA_STATUSCODE_GOOD) {
+ /* Configuration of all Components that belong to this connection: */
+ res = createComponentsForConnection(server, connParams, connectionIdent,
+ pdsCount, pdsIdent);
+ } else {
+ UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
+ "[UA_PubSubManager_createPubSubConnection] "
+ "Connection creation failed");
+ }
+
+ return res;
+}
+
+/* Function called by UA_PubSubManager_createWriterGroup to configure the messageSettings
+ * of a writerGroup */
+static UA_StatusCode
+setWriterGroupEncodingType(const UA_WriterGroupDataType *writerGroupParameters,
+ UA_WriterGroupConfig *config) {
+ if(writerGroupParameters->messageSettings.encoding != UA_EXTENSIONOBJECT_DECODED) {
+ UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
+ "[UA_PubSubManager_setWriterGroupEncodingType] "
+ "getting message type information failed");
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+ }
+
+ if(writerGroupParameters->messageSettings.content.decoded.type ==
+ &UA_TYPES[UA_TYPES_UADPWRITERGROUPMESSAGEDATATYPE]) {
+ config->encodingMimeType = UA_PUBSUB_ENCODING_UADP;
+ } else if(writerGroupParameters->messageSettings.content.decoded.type ==
+ &UA_TYPES[UA_TYPES_JSONWRITERGROUPMESSAGEDATATYPE]) {
+ UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
+ "[UA_PubSubManager_setWriterGroupEncodingType] "
+ "encoding type: JSON (not implemented!)");
+ return UA_STATUSCODE_BADNOTIMPLEMENTED;
+ } else {
+ UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
+ "[UA_PubSubManager_setWriterGroupEncodingType] "
+ "invalid message encoding type");
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+ }
+
+ return UA_STATUSCODE_GOOD;
+}
+
+/* WriterGroup configuration from WriterGroup object
+ *
+ * @param server Server object that shall be configured
+ * @param writerGroupParameters WriterGroup configuration
+ * @param connectionIdent NodeId of the PubSub connection, the WriterGroup belongs to
+ * @param pdsCount Number of published DataSets
+ * @param pdsIdent Array of NodeIds of the published DataSets */
+static UA_StatusCode
+createWriterGroup(UA_Server *server,
+ const UA_WriterGroupDataType *writerGroupParameters,
+ UA_NodeId connectionIdent, UA_UInt32 pdsCount,
+ const UA_NodeId *pdsIdent) {
+ UA_WriterGroupConfig config;
+ memset(&config, 0, sizeof(UA_WriterGroupConfig));
+ config.name = writerGroupParameters->name;
+ config.enabled = writerGroupParameters->enabled;
+ config.writerGroupId = writerGroupParameters->writerGroupId;
+ config.publishingInterval = writerGroupParameters->publishingInterval;
+ config.keepAliveTime = writerGroupParameters->keepAliveTime;
+ config.priority = writerGroupParameters->priority;
+ config.securityMode = writerGroupParameters->securityMode;
+ config.transportSettings = writerGroupParameters->transportSettings;
+ config.messageSettings = writerGroupParameters->messageSettings;
+ config.groupPropertiesSize = writerGroupParameters->groupPropertiesSize;
+ if(config.groupPropertiesSize > 0)
+ config.groupProperties = writerGroupParameters->groupProperties;
+
+ config.maxEncapsulatedDataSetMessageCount = 255; /* non std parameter */
+
+ UA_StatusCode res = setWriterGroupEncodingType(writerGroupParameters, &config);
+ if(res != UA_STATUSCODE_GOOD) {
+ UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
+ "[UA_PubSubManager_createWriterGroup] "
+ "Setting message settings failed");
+ return res;
+ }
+
+ /* Load config into server: */
+ UA_NodeId writerGroupIdent;
+ res = UA_Server_addWriterGroup(server, connectionIdent, &config, &writerGroupIdent);
+ UA_Server_setWriterGroupOperational(server, writerGroupIdent);
+ if(res != UA_STATUSCODE_GOOD) {
+ UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
+ "[UA_PubSubManager_createWriterGroup] "
+ "Adding WriterGroup to server failed: 0x%x", res);
+ return res;
+ }
+
+ /* Configuration of all DataSetWriters that belong to this WriterGroup */
+ for(size_t dsw = 0; dsw < writerGroupParameters->dataSetWritersSize; dsw++) {
+ res = createDataSetWriter(server, &writerGroupParameters->dataSetWriters[dsw],
+ writerGroupIdent, pdsCount, pdsIdent);
+ if(res != UA_STATUSCODE_GOOD) {
+ UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
+ "[UA_PubSubManager_createWriterGroup] "
+ "DataSetWriter Creation failed.");
+ break;
+ }
+ }
+ return res;
+}
+
+/* Function called by UA_PubSubManager_createDataSetWriter. It searches for a
+ * PublishedDataSet that is referenced by the DataSetWriter. If a related PDS is found,
+ * the DSWriter will be added to the server, otherwise, no DSWriter will be added.
+ *
+ * @param server UA_Server object that shall be configured
+ * @param writerGroupIdent NodeId of writerGroup, the DataSetWriter belongs to
+ * @param dsWriterConfig WriterGroup configuration
+ * @param pdsCount Number of published DataSets
+ * @param pdsIdent Array of NodeIds of the published DataSets */
+static UA_StatusCode
+addDataSetWriterWithPdsReference(UA_Server *server, UA_NodeId writerGroupIdent,
+ const UA_DataSetWriterConfig *dsWriterConfig,
+ UA_UInt32 pdsCount, const UA_NodeId *pdsIdent) {
+ UA_NodeId dataSetWriterIdent;
+ UA_PublishedDataSetConfig pdsConfig;
+ UA_Boolean pdsFound = false;
+
+ UA_StatusCode res = UA_STATUSCODE_GOOD;
+ for(size_t pds = 0; pds < pdsCount && res == UA_STATUSCODE_GOOD; pds++) {
+ res = UA_Server_getPublishedDataSetConfig(server, pdsIdent[pds], &pdsConfig);
+ /* members of pdsConfig must be deleted manually */
+ if(res != UA_STATUSCODE_GOOD) {
+ UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
+ "[UA_PubSubManager_addDataSetWriterWithPdsReference] "
+ "Getting pdsConfig from NodeId failed.");
+ return res;
+ }
+
+ if(dsWriterConfig->dataSetName.length == pdsConfig.name.length &&
+ 0 == strncmp((const char *)dsWriterConfig->dataSetName.data,
+ (const char *)pdsConfig.name.data,
+ dsWriterConfig->dataSetName.length)) {
+ /* DSWriter will only be created, if a matching PDS is found: */
+ res = UA_Server_addDataSetWriter(server, writerGroupIdent, pdsIdent[pds],
+ dsWriterConfig, &dataSetWriterIdent);
+ if(res != UA_STATUSCODE_GOOD) {
+ UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
+ "[UA_PubSubManager_addDataSetWriterWithPdsReference] "
+ "Adding DataSetWriter failed");
+ } else {
+ pdsFound = true;
+ }
+
+ UA_PublishedDataSetConfig_clear(&pdsConfig);
+ if(pdsFound)
+ break; /* break loop if corresponding publishedDataSet was found */
+ }
+ }
+
+ if(!pdsFound) {
+ UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
+ "[UA_PubSubManager_addDataSetWriterWithPdsReference] "
+ "No matching DataSet found; no DataSetWriter created");
+ }
+
+ return res;
+}
+
+/* Creates DataSetWriter configuration from DataSetWriter object
+ *
+ * @param server UA_Server object that shall be configured
+ * @param dataSetWriterParameters DataSetWriter Configuration
+ * @param writerGroupIdent NodeId of writerGroup, the DataSetWriter belongs to
+ * @param pdsCount Number of published DataSets
+ * @param pdsIdent Array of NodeIds of the published DataSets */
+static UA_StatusCode
+createDataSetWriter(UA_Server *server,
+ const UA_DataSetWriterDataType *dataSetWriterParameters,
+ UA_NodeId writerGroupIdent, UA_UInt32 pdsCount,
+ const UA_NodeId *pdsIdent) {
+ UA_DataSetWriterConfig config;
+ memset(&config, 0, sizeof(UA_DataSetWriterConfig));
+ config.name = dataSetWriterParameters->name;
+ config.dataSetWriterId = dataSetWriterParameters->dataSetWriterId;
+ config.keyFrameCount = dataSetWriterParameters->keyFrameCount;
+ config.dataSetFieldContentMask = dataSetWriterParameters->dataSetFieldContentMask;
+ config.messageSettings = dataSetWriterParameters->messageSettings;
+ config.dataSetName = dataSetWriterParameters->dataSetName;
+ config.dataSetWriterPropertiesSize = dataSetWriterParameters->dataSetWriterPropertiesSize;
+ if(config.dataSetWriterPropertiesSize > 0)
+ config.dataSetWriterProperties = dataSetWriterParameters->dataSetWriterProperties;
+
+ UA_StatusCode res = addDataSetWriterWithPdsReference(server, writerGroupIdent,
+ &config, pdsCount, pdsIdent);
+ if(res != UA_STATUSCODE_GOOD) {
+ UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
+ "[UA_PubSubManager_createDataSetWriter] "
+ "Referencing related PDS failed");
+ }
+
+ return res;
+}
+
+/* Creates ReaderGroup configuration from ReaderGroup object
+ *
+ * @param server UA_Server object that shall be configured
+ * @param readerGroupParameters ReaderGroup configuration
+ * @param connectionIdent NodeId of the PubSub connection, the ReaderGroup belongs to */
+static UA_StatusCode
+createReaderGroup(UA_Server *server,
+ const UA_ReaderGroupDataType *readerGroupParameters,
+ UA_NodeId connectionIdent) {
+ UA_ReaderGroupConfig config;
+ memset(&config, 0, sizeof(UA_ReaderGroupConfig));
+
+ config.name = readerGroupParameters->name;
+ config.securityParameters.securityMode = readerGroupParameters->securityMode;
+
+ UA_NodeId readerGroupIdent;
+ UA_StatusCode res =
+ UA_Server_addReaderGroup(server, connectionIdent, &config, &readerGroupIdent);
+ if(res != UA_STATUSCODE_GOOD) {
+ UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
+ "[UA_PubSubManager_createReaderGroup] Adding ReaderGroup "
+ "to server failed: 0x%x", res);
+ return res;
+ }
+
+ UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
+ "[UA_PubSubManager_createReaderGroup] ReaderGroup successfully added.");
+ for(UA_UInt32 i = 0; i < readerGroupParameters->dataSetReadersSize; i++) {
+ res = createDataSetReader(server, &readerGroupParameters->dataSetReaders[i],
+ readerGroupIdent);
+ if(res != UA_STATUSCODE_GOOD) {
+ UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
+ "[UA_PubSubManager_createReaderGroup] Creating DataSetReader failed");
+ break;
+ }
+ }
+
+ if(res == UA_STATUSCODE_GOOD)
+ UA_Server_setReaderGroupOperational(server, readerGroupIdent);
+
+ return res;
+}
+
+/* Creates TargetVariables or SubscribedDataSetMirror for a given DataSetReader
+ *
+ * @param server UA_Server object that shall be configured
+ * @param dsReaderIdent NodeId of the DataSetReader the SubscribedDataSet belongs to
+ * @param dataSetReaderParameters Configuration Parameters of the DataSetReader */
+static UA_StatusCode
+addSubscribedDataSet(UA_Server *server, const UA_NodeId dsReaderIdent,
+ const UA_ExtensionObject *subscribedDataSet) {
+ if(subscribedDataSet->content.decoded.type ==
+ &UA_TYPES[UA_TYPES_TARGETVARIABLESDATATYPE]) {
+ UA_TargetVariablesDataType *tmpTargetVars = (UA_TargetVariablesDataType*)
+ subscribedDataSet->content.decoded.data;
+ UA_FieldTargetVariable *targetVars = (UA_FieldTargetVariable *)
+ UA_calloc(tmpTargetVars->targetVariablesSize, sizeof(UA_FieldTargetVariable));
+
+ for(size_t index = 0; index < tmpTargetVars->targetVariablesSize; index++) {
+ UA_FieldTargetDataType_copy(&tmpTargetVars->targetVariables[index],
+ &targetVars[index].targetVariable);
+ }
+
+ UA_StatusCode res =
+ UA_Server_DataSetReader_createTargetVariables(server, dsReaderIdent,
+ tmpTargetVars->targetVariablesSize,
+ targetVars);
+ if(res != UA_STATUSCODE_GOOD) {
+ UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
+ "[UA_PubSubManager_addSubscribedDataSet] "
+ "create TargetVariables failed");
+ }
+
+ for(size_t index = 0; index < tmpTargetVars->targetVariablesSize; index++) {
+ UA_FieldTargetDataType_clear(&targetVars[index].targetVariable);
+ }
+
+ UA_free(targetVars);
+ return res;
+ }
+
+ if(subscribedDataSet->content.decoded.type ==
+ &UA_TYPES[UA_TYPES_SUBSCRIBEDDATASETMIRRORDATATYPE]) {
+ UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
+ "[UA_PubSubManager_addSubscribedDataSet] "
+ "DataSetMirror is currently not supported");
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+ }
+
+ UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
+ "[UA_PubSubManager_addSubscribedDataSet] "
+ "Invalid Type of SubscribedDataSet");
+ return UA_STATUSCODE_BADINTERNALERROR;
+}
+
+/* Creates DataSetReader configuration from DataSetReader object
+ *
+ * @param server UA_Server object that shall be configured
+ * @param dataSetReaderParameters DataSetReader configuration
+ * @param writerGroupIdent NodeId of readerGroupParameters, the DataSetReader belongs to */
+static UA_StatusCode
+createDataSetReader(UA_Server *server, const UA_DataSetReaderDataType *dsrParams,
+ UA_NodeId readerGroupIdent) {
+ UA_DataSetReaderConfig config;
+ memset(&config, 0, sizeof(UA_DataSetReaderConfig));
+
+ config.name = dsrParams->name;
+ config.publisherId = dsrParams->publisherId;
+ config.writerGroupId = dsrParams->writerGroupId;
+ config.dataSetWriterId = dsrParams->dataSetWriterId;
+ config.dataSetMetaData = dsrParams->dataSetMetaData;
+ config.dataSetFieldContentMask = dsrParams->dataSetFieldContentMask;
+ config.messageReceiveTimeout = dsrParams->messageReceiveTimeout;
+ config.messageSettings = dsrParams->messageSettings;
+
+ UA_NodeId dsReaderIdent;
+ UA_StatusCode res = UA_Server_addDataSetReader(server, readerGroupIdent,
+ &config, &dsReaderIdent);
+ if(res == UA_STATUSCODE_GOOD)
+ res = addSubscribedDataSet(server, dsReaderIdent,
+ &dsrParams->subscribedDataSet);
+ if(res != UA_STATUSCODE_GOOD) {
+ UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
+ "[UA_PubSubManager_createDataSetReader] "
+ "create subscribedDataSet failed");
+ }
+
+ return res;
+}
+
+/* Determines whether PublishedDataSet is of type PublishedItems or PublishedEvents.
+ * (PublishedEvents are currently not supported!)
+ *
+ * @param publishedDataSetParameters PublishedDataSet parameters
+ * @param config PublishedDataSet configuration object */
+static UA_StatusCode
+setPublishedDataSetType(const UA_PublishedDataSetDataType *pdsParams,
+ UA_PublishedDataSetConfig *config) {
+ if(pdsParams->dataSetSource.encoding != UA_EXTENSIONOBJECT_DECODED)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ const UA_DataType *sourceType = pdsParams->dataSetSource.content.decoded.type;
+ if(sourceType == &UA_TYPES[UA_TYPES_PUBLISHEDDATAITEMSDATATYPE]) {
+ config->publishedDataSetType = UA_PUBSUB_DATASET_PUBLISHEDITEMS;
+ return UA_STATUSCODE_GOOD;
+ } else if(sourceType == &UA_TYPES[UA_TYPES_PUBLISHEDEVENTSDATATYPE]) {
+ /* config.publishedDataSetType = UA_PUBSUB_DATASET_PUBLISHEDEVENTS; */
+ UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
+ "[UA_PubSubManager_setPublishedDataSetType] Published events not supported.");
+ return UA_STATUSCODE_BADNOTIMPLEMENTED;
+ }
+
+ UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
+ "[UA_PubSubManager_setPublishedDataSetType] Invalid DataSetSourceDataType.");
+ return UA_STATUSCODE_BADINTERNALERROR;
+}
+
+/* Creates PublishedDataSetConfig object from PublishedDataSet object
+ *
+ * @param server UA_Server object that shall be configured
+ * @param pdsParams publishedDataSet configuration
+ * @param pdsIdent NodeId of the publishedDataSet */
+static UA_StatusCode
+createPublishedDataSet(UA_Server *server,
+ const UA_PublishedDataSetDataType *pdsParams,
+ UA_NodeId *pdsIdent) {
+ UA_PublishedDataSetConfig config;
+ memset(&config, 0, sizeof(UA_PublishedDataSetConfig));
+
+ config.name = pdsParams->name;
+ UA_StatusCode res = setPublishedDataSetType(pdsParams, &config);
+ if(res != UA_STATUSCODE_GOOD)
+ return res;
+
+ res = UA_Server_addPublishedDataSet(server, &config, pdsIdent).addResult;
+ if(res != UA_STATUSCODE_GOOD) {
+ UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
+ "[UA_PubSubManager_createPublishedDataSet] "
+ "Adding PublishedDataSet failed.");
+ return res;
+ }
+
+ /* DataSetField configuration for this publishedDataSet: */
+ res = createDataSetFields(server, pdsIdent, pdsParams);
+ if(res != UA_STATUSCODE_GOOD) {
+ UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
+ "[UA_PubSubManager_createPublishedDataSet] "
+ "Creating DataSetFieldConfig failed.");
+ }
+
+ return res;
+}
+
+/* Adds DataSetField Variables bound to a certain PublishedDataSet. This method does NOT
+ * check, whether the PublishedDataSet actually contains Variables instead of Events!
+ *
+ * @param server UA_Server object that shall be configured
+ * @param pdsIdent NodeId of the publishedDataSet, the DataSetField belongs to
+ * @param publishedDataSetParameters publishedDataSet configuration */
+static UA_StatusCode
+addDataSetFieldVariables(UA_Server *server, const UA_NodeId *pdsIdent,
+ const UA_PublishedDataSetDataType *pdsParams) {
+ UA_PublishedDataItemsDataType *pdItems = (UA_PublishedDataItemsDataType *)
+ pdsParams->dataSetSource.content.decoded.data;
+ if(pdItems->publishedDataSize != pdsParams->dataSetMetaData.fieldsSize)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ for(size_t i = 0; i < pdItems->publishedDataSize; i++) {
+ UA_DataSetFieldConfig fc;
+ memset(&fc, 0, sizeof(UA_DataSetFieldConfig));
+ fc.dataSetFieldType = UA_PUBSUB_DATASETFIELD_VARIABLE;
+ fc.field.variable.configurationVersion = pdsParams->dataSetMetaData.configurationVersion;
+ fc.field.variable.fieldNameAlias = pdsParams->dataSetMetaData.fields[i].name;
+ fc.field.variable.promotedField = pdsParams->dataSetMetaData.
+ fields[i].fieldFlags & 0x0001;
+ fc.field.variable.publishParameters = pdItems->publishedData[i];
+
+ UA_NodeId fieldIdent;
+ UA_StatusCode res = UA_Server_addDataSetField(server, *pdsIdent, &fc, &fieldIdent).result;
+ if(res != UA_STATUSCODE_GOOD) {
+ UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
+ "[UA_PubSubManager_addDataSetFieldVariables] "
+ "Adding DataSetField Variable failed.");
+ return res;
+ }
+ }
+
+ return UA_STATUSCODE_GOOD;
+}
+
+/* Checks if PublishedDataSet contains event or variable fields and calls the
+ * corresponding method to add these fields to the server.
+ *
+ * @param server UA_Server object that shall be configured
+ * @param pdsIdent NodeId of the publishedDataSet, the DataSetFields belongs to
+ * @param pdsParams publishedDataSet configuration */
+static UA_StatusCode
+createDataSetFields(UA_Server *server, const UA_NodeId *pdsIdent,
+ const UA_PublishedDataSetDataType *pdsParams) {
+ if(pdsParams->dataSetSource.encoding != UA_EXTENSIONOBJECT_DECODED)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ if(pdsParams->dataSetSource.content.decoded.type ==
+ &UA_TYPES[UA_TYPES_PUBLISHEDDATAITEMSDATATYPE])
+ return addDataSetFieldVariables(server, pdsIdent, pdsParams);
+
+ /* TODO: Implement Routine for adding Event DataSetFields */
+ if(pdsParams->dataSetSource.content.decoded.type ==
+ &UA_TYPES[UA_TYPES_PUBLISHEDEVENTSDATATYPE]) {
+ UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
+ "[UA_PubSubManager_createDataSetFields] "
+ "Published events not supported.");
+ return UA_STATUSCODE_BADNOTIMPLEMENTED;
+ }
+
+ UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
+ "[UA_PubSubManager_createDataSetFields] "
+ "Invalid DataSetSourceDataType.");
+ return UA_STATUSCODE_BADINTERNALERROR;
+}
+
+UA_StatusCode
+UA_PubSubManager_loadPubSubConfigFromByteString(UA_Server *server,
+ const UA_ByteString buffer) {
+ size_t offset = 0;
+ UA_ExtensionObject decodedFile;
+ UA_StatusCode res = UA_ExtensionObject_decodeBinary(&buffer, &offset, &decodedFile);
+ if(res != UA_STATUSCODE_GOOD) {
+ UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
+ "[UA_decodeBinFile] decoding UA_Binary failed");
+ goto cleanup;
+ }
+
+ UA_PubSubConfigurationDataType *pubSubConfig = NULL;
+ res = extractPubSubConfigFromExtensionObject(&decodedFile, &pubSubConfig);
+ if(res != UA_STATUSCODE_GOOD) {
+ UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
+ "[UA_PubSubManager_loadPubSubConfigFromByteString] "
+ "Extracting PubSub Configuration failed");
+ goto cleanup;
+ }
+
+ res = updatePubSubConfig(server, pubSubConfig);
+ if(res != UA_STATUSCODE_GOOD) {
+ UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
+ "[UA_PubSubManager_loadPubSubConfigFromByteString] "
+ "Loading PubSub configuration into server failed");
+ goto cleanup;
+ }
+
+ cleanup:
+ UA_ExtensionObject_clear(&decodedFile);
+ return res;
+}
+
+/* Encodes a PubSubConfigurationDataType object as ByteString using the UA Binary Data
+ * Encoding */
+static UA_StatusCode
+encodePubSubConfiguration(UA_PubSubConfigurationDataType *configurationParameters,
+ UA_ByteString *buffer) {
+ UA_UABinaryFileDataType binFile;
+ memset(&binFile, 0, sizeof(UA_UABinaryFileDataType));
+ /*Perhaps, additional initializations of binFile are necessary here.*/
+
+ UA_Variant_setScalar(&binFile.body, configurationParameters,
+ &UA_TYPES[UA_TYPES_PUBSUBCONFIGURATIONDATATYPE]);
+
+ UA_ExtensionObject container;
+ memset(&container, 0, sizeof(UA_ExtensionObject));
+ container.encoding = UA_EXTENSIONOBJECT_DECODED;
+ container.content.decoded.type = &UA_TYPES[UA_TYPES_UABINARYFILEDATATYPE];
+ container.content.decoded.data = &binFile;
+
+ size_t fileSize = UA_ExtensionObject_calcSizeBinary(&container);
+ buffer->data = (UA_Byte*)UA_calloc(fileSize, sizeof(UA_Byte));
+ if(buffer->data == NULL) {
+ UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
+ "[UA_PubSubManager_encodePubSubConfiguration] Allocating buffer failed");
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ }
+
+ buffer->length = fileSize;
+
+ UA_Byte *bufferPos = buffer->data;
+ UA_StatusCode res =
+ UA_ExtensionObject_encodeBinary(&container, &bufferPos, bufferPos + fileSize);
+ if(res != UA_STATUSCODE_GOOD) {
+ UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
+ "[UA_PubSubManager_encodePubSubConfiguration] Encoding failed");
+ }
+ return res;
+}
+
+static UA_StatusCode
+generatePublishedDataSetDataType(const UA_PublishedDataSet *src,
+ UA_PublishedDataSetDataType *dst) {
+ if(src->config.publishedDataSetType != UA_PUBSUB_DATASET_PUBLISHEDITEMS)
+ return UA_STATUSCODE_BADNOTIMPLEMENTED;
+
+ memset(dst, 0, sizeof(UA_PublishedDataSetDataType));
+
+ UA_PublishedDataItemsDataType *tmp = UA_PublishedDataItemsDataType_new();
+ UA_String_copy(&src->config.name, &dst->name);
+ dst->dataSetMetaData.fieldsSize = src->fieldSize;
+
+ size_t index = 0;
+ tmp->publishedDataSize = src->fieldSize;
+ tmp->publishedData = (UA_PublishedVariableDataType*)
+ UA_Array_new(tmp->publishedDataSize, &UA_TYPES[UA_TYPES_PUBLISHEDVARIABLEDATATYPE]);
+ if(tmp->publishedData == NULL) {
+ UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "Allocation memory failed");
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ }
+
+ dst->dataSetMetaData.fields = (UA_FieldMetaData*)
+ UA_Array_new(dst->dataSetMetaData.fieldsSize, &UA_TYPES[UA_TYPES_FIELDMETADATA]);
+ if(dst->dataSetMetaData.fields == NULL) {
+ UA_free(tmp->publishedData);
+ UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "Allocation memory failed");
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ }
+
+ UA_DataSetField *dsf, *dsf_tmp = NULL;
+ TAILQ_FOREACH_SAFE(dsf ,&src->fields, listEntry, dsf_tmp) {
+ UA_String_copy(&dsf->config.field.variable.fieldNameAlias,
+ &dst->dataSetMetaData.fields[index].name);
+ UA_PublishedVariableDataType_copy(&dsf->config.field.variable.publishParameters,
+ &tmp->publishedData[index]);
+ UA_ConfigurationVersionDataType_copy(&dsf->config.field.variable.configurationVersion,
+ &dst->dataSetMetaData.configurationVersion);
+ dst->dataSetMetaData.fields[index].fieldFlags =
+ dsf->config.field.variable.promotedField;
+ index++;
+ }
+ UA_ExtensionObject_setValue(&dst->dataSetSource, tmp,
+ &UA_TYPES[UA_TYPES_PUBLISHEDDATAITEMSDATATYPE]);
+
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_StatusCode
+generateDataSetWriterDataType(const UA_DataSetWriter *src,
+ UA_DataSetWriterDataType *dst) {
+ memset(dst, 0, sizeof(UA_DataSetWriterDataType));
+
+ UA_String_copy(&src->config.name, &dst->name);
+ dst->dataSetWriterId = src->config.dataSetWriterId;
+ dst->keyFrameCount = src->config.keyFrameCount;
+ dst->dataSetFieldContentMask = src->config.dataSetFieldContentMask;
+ UA_ExtensionObject_copy(&src->config.messageSettings, &dst->messageSettings);
+ UA_String_copy(&src->config.dataSetName, &dst->dataSetName);
+
+ dst->dataSetWriterPropertiesSize = src->config.dataSetWriterPropertiesSize;
+ for(size_t i = 0; i < src->config.dataSetWriterPropertiesSize; i++) {
+ UA_KeyValuePair_copy(&src->config.dataSetWriterProperties[i],
+ &dst->dataSetWriterProperties[i]);
+ }
+
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_StatusCode
+generateWriterGroupDataType(const UA_WriterGroup *src,
+ UA_WriterGroupDataType *dst) {
+ memset(dst, 0, sizeof(UA_WriterGroupDataType));
+
+ UA_String_copy(&src->config.name, &dst->name);
+ dst->enabled = src->config.enabled;
+ dst->writerGroupId = src->config.writerGroupId;
+ dst->publishingInterval = src->config.publishingInterval;
+ dst->keepAliveTime = src->config.keepAliveTime;
+ dst->priority = src->config.priority;
+ dst->securityMode = src->config.securityMode;
+
+ UA_ExtensionObject_copy(&src->config.transportSettings, &dst->transportSettings);
+ UA_ExtensionObject_copy(&src->config.messageSettings, &dst->messageSettings);
+
+ dst->groupPropertiesSize = src->config.groupPropertiesSize;
+ dst->groupProperties = (UA_KeyValuePair*)
+ UA_Array_new(dst->groupPropertiesSize, &UA_TYPES[UA_TYPES_KEYVALUEPAIR]);
+ for(size_t index = 0; index < dst->groupPropertiesSize; index++) {
+ UA_KeyValuePair_copy(&src->config.groupProperties[index],
+ &dst->groupProperties[index]);
+ }
+
+ dst->dataSetWriters = (UA_DataSetWriterDataType*)
+ UA_calloc(src->writersCount, sizeof(UA_DataSetWriterDataType));
+ if(!dst->dataSetWriters)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+
+ dst->dataSetWritersSize = src->writersCount;
+
+ UA_DataSetWriter *dsw;
+ size_t dsWriterIndex = 0;
+ LIST_FOREACH(dsw, &src->writers, listEntry) {
+ UA_StatusCode res =
+ generateDataSetWriterDataType(dsw, &dst->dataSetWriters[dsWriterIndex]);
+ if(res != UA_STATUSCODE_GOOD)
+ return res;
+ dsWriterIndex++;
+ }
+
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_StatusCode
+generateDataSetReaderDataType(const UA_DataSetReader *src,
+ UA_DataSetReaderDataType *dst) {
+ UA_StatusCode res = UA_STATUSCODE_GOOD;
+ memset(dst, 0, sizeof(UA_DataSetReaderDataType));
+ dst->writerGroupId = src->config.writerGroupId;
+ dst->dataSetWriterId = src->config.dataSetWriterId;
+ dst->dataSetFieldContentMask = src->config.dataSetFieldContentMask;
+ dst->messageReceiveTimeout = src->config.messageReceiveTimeout;
+ res |= UA_String_copy(&src->config.name, &dst->name);
+ res |= UA_Variant_copy(&src->config.publisherId, &dst->publisherId);
+ res |= UA_DataSetMetaDataType_copy(&src->config.dataSetMetaData,
+ &dst->dataSetMetaData);
+ res |= UA_ExtensionObject_copy(&src->config.messageSettings, &dst->messageSettings);
+
+ UA_TargetVariablesDataType *tmpTarget = UA_TargetVariablesDataType_new();
+ if(!tmpTarget)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ UA_ExtensionObject_setValue(&dst->subscribedDataSet, tmpTarget,
+ &UA_TYPES[UA_TYPES_TARGETVARIABLESDATATYPE]);
+
+ const UA_TargetVariables *targets =
+ &src->config.subscribedDataSet.subscribedDataSetTarget;
+ tmpTarget->targetVariables = (UA_FieldTargetDataType *)
+ UA_calloc(targets->targetVariablesSize, sizeof(UA_FieldTargetDataType));
+ if(!tmpTarget->targetVariables)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ tmpTarget->targetVariablesSize = targets->targetVariablesSize;
+
+ for(size_t i = 0; i < tmpTarget->targetVariablesSize; i++) {
+ res |= UA_FieldTargetDataType_copy(&targets->targetVariables[i].targetVariable,
+ &tmpTarget->targetVariables[i]);
+ }
+
+ return res;
+}
+
+static UA_StatusCode
+generateReaderGroupDataType(const UA_ReaderGroup *src,
+ UA_ReaderGroupDataType *dst) {
+ memset(dst, 0, sizeof(UA_ReaderGroupDataType));
+
+ UA_String_copy(&src->config.name, &dst->name);
+ dst->dataSetReaders = (UA_DataSetReaderDataType*)
+ UA_calloc(src->readersCount, sizeof(UA_DataSetReaderDataType));
+ if(dst->dataSetReaders == NULL)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ dst->dataSetReadersSize = src->readersCount;
+
+ size_t i = 0;
+ UA_DataSetReader *dsr, *dsr_tmp = NULL;
+ LIST_FOREACH_SAFE(dsr, &src->readers, listEntry, dsr_tmp) {
+ UA_StatusCode res =
+ generateDataSetReaderDataType(dsr, &dst->dataSetReaders[i]);
+ if(res != UA_STATUSCODE_GOOD)
+ return res;
+ i++;
+ }
+
+ return UA_STATUSCODE_GOOD;
+}
+
+/* Generates a PubSubConnectionDataType object from a PubSubConnection. */
+static UA_StatusCode
+generatePubSubConnectionDataType(const UA_PubSubConnection *src,
+ UA_PubSubConnectionDataType *dst) {
+ memset(dst, 0, sizeof(UA_PubSubConnectionDataType));
+
+ UA_String_copy(&src->config->name, &dst->name);
+ UA_String_copy(&src->config->transportProfileUri, &dst->transportProfileUri);
+ dst->enabled = src->config->enabled;
+
+ dst->connectionPropertiesSize = src->config->connectionPropertiesSize;
+ for(size_t i = 0; i < src->config->connectionPropertiesSize; i++) {
+ UA_KeyValuePair_copy(&src->config->connectionProperties[i],
+ &dst->connectionProperties[i]);
+ }
+
+ if(src->config->publisherIdType == UA_PUBSUB_PUBLISHERID_NUMERIC) {
+ UA_Variant_setScalarCopy(&dst->publisherId,
+ &src->config->publisherId.numeric,
+ &UA_TYPES[UA_TYPES_UINT32]);
+ } else if(src->config->publisherIdType == UA_PUBSUB_PUBLISHERID_STRING) {
+ UA_Variant_setScalarCopy(&dst->publisherId,
+ &src->config->publisherId.string,
+ &UA_TYPES[UA_TYPES_STRING]);
+ }
+
+ /* Possibly, array size and dimensions of src->config->address and
+ * src->config->connectionTransportSettings should be checked beforehand. */
+ dst->address.encoding = UA_EXTENSIONOBJECT_DECODED;
+ dst->address.content.decoded.type = src->config->address.type;
+ UA_StatusCode res =
+ UA_Array_copy(src->config->address.data, 1,
+ &dst->address.content.decoded.data, src->config->address.type);
+ if(res != UA_STATUSCODE_GOOD)
+ return res;
+
+ if(src->config->connectionTransportSettings.data) {
+ dst->transportSettings.encoding = UA_EXTENSIONOBJECT_DECODED;
+ dst->transportSettings.content.decoded.type =
+ src->config->connectionTransportSettings.type;
+ res = UA_Array_copy(src->config->connectionTransportSettings.data, 1,
+ &dst->transportSettings.content.decoded.data,
+ src->config->connectionTransportSettings.type);
+
+ if(res != UA_STATUSCODE_GOOD)
+ return res;
+ }
+
+ dst->writerGroups = (UA_WriterGroupDataType*)
+ UA_calloc(src->writerGroupsSize, sizeof(UA_WriterGroupDataType));
+ if(dst->writerGroups == NULL) {
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ }
+
+ dst->writerGroupsSize = src->writerGroupsSize;
+ UA_WriterGroup *wg, *wg_tmp = NULL;
+ size_t wgIndex = 0;
+ LIST_FOREACH_SAFE(wg ,&src->writerGroups, listEntry, wg_tmp) {
+ res = generateWriterGroupDataType(wg, &dst->writerGroups[wgIndex]);
+ if(res != UA_STATUSCODE_GOOD)
+ return res;
+ wgIndex++;
+ }
+
+ dst->readerGroups = (UA_ReaderGroupDataType*)
+ UA_calloc(src->readerGroupsSize, sizeof(UA_ReaderGroupDataType));
+ if(dst->readerGroups == NULL) {
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ }
+
+ dst->readerGroupsSize = src->readerGroupsSize;
+ UA_ReaderGroup *rg = NULL;
+ size_t rgIndex = 0;
+ LIST_FOREACH(rg, &src->readerGroups, listEntry) {
+ res = generateReaderGroupDataType(rg, &dst->readerGroups[rgIndex]);
+ if(res != UA_STATUSCODE_GOOD)
+ return res;
+ rgIndex++;
+ }
+
+ return UA_STATUSCODE_GOOD;
+}
+
+UA_StatusCode
+generatePubSubConfigurationDataType(const UA_Server* server,
+ UA_PubSubConfigurationDataType *configDT) {
+ UA_StatusCode res = UA_STATUSCODE_GOOD;
+ const UA_PubSubManager *manager = &server->pubSubManager;
+ memset(configDT, 0, sizeof(UA_PubSubConfigurationDataType));
+
+ configDT->publishedDataSets = (UA_PublishedDataSetDataType*)
+ UA_calloc(manager->publishedDataSetsSize,
+ sizeof(UA_PublishedDataSetDataType));
+ if(configDT->publishedDataSets == NULL)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ configDT->publishedDataSetsSize = manager->publishedDataSetsSize;
+
+ UA_PublishedDataSet *pds;
+ UA_UInt32 pdsIndex = 0;
+ TAILQ_FOREACH(pds, &manager->publishedDataSets, listEntry) {
+ UA_PublishedDataSetDataType *dst = &configDT->publishedDataSets[pdsIndex];
+ res = generatePublishedDataSetDataType(pds, dst);
+ if(res != UA_STATUSCODE_GOOD) {
+ UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
+ "[UA_PubSubManager_generatePubSubConfigurationDataType] "
+ "retrieving PublishedDataSet configuration failed");
+ return res;
+ }
+ pdsIndex++;
+ }
+
+ configDT->connections = (UA_PubSubConnectionDataType*)
+ UA_calloc(manager->connectionsSize, sizeof(UA_PubSubConnectionDataType));
+ if(configDT->connections == NULL)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ configDT->connectionsSize = manager->connectionsSize;
+
+ UA_UInt32 connectionIndex = 0;
+ UA_PubSubConnection *connection;
+ TAILQ_FOREACH(connection, &manager->connections, listEntry) {
+ UA_PubSubConnectionDataType *cdt = &configDT->connections[connectionIndex];
+ res = generatePubSubConnectionDataType(connection, cdt);
+ if(res != UA_STATUSCODE_GOOD) {
+ UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
+ "[UA_PubSubManager_generatePubSubConfigurationDataType] "
+ "retrieving PubSubConnection configuration failed");
+ return res;
+ }
+ connectionIndex++;
+ }
+
+ return UA_STATUSCODE_GOOD;
+}
+
+UA_StatusCode
+UA_PubSubManager_getEncodedPubSubConfiguration(UA_Server *server,
+ UA_ByteString *buffer) {
+ UA_PubSubConfigurationDataType config;
+ memset(&config, 0, sizeof(UA_PubSubConfigurationDataType));
+
+ UA_StatusCode res = generatePubSubConfigurationDataType(server, &config);
+ if(res != UA_STATUSCODE_GOOD) {
+ UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
+ "retrieving PubSub configuration from server failed");
+ goto cleanup;
+ }
+
+ res = encodePubSubConfiguration(&config, buffer);
+ if(res != UA_STATUSCODE_GOOD) {
+ UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
+ "encoding PubSub configuration failed");
+ goto cleanup;
+ }
+
+ UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
+ "Saving PubSub config was successful");
+
+ cleanup:
+ UA_PubSubConfigurationDataType_clear(&config);
+ return res;
+}
+
+#endif /* UA_ENABLE_PUBSUB_FILE_CONFIG */
+
+/**** amalgamated original file "/build/src_generated/open62541/namespace0_generated.c" ****/
/* WARNING: This is a generated file.
* Any manual changes will be overwritten. */
@@ -46272,9 +51978,9 @@ UA_ReferenceTypeAttributes attr = UA_ReferenceTypeAttributes_default;
attr.inverseName = UA_LOCALIZEDTEXT("", "AddInOf");
attr.displayName = UA_LOCALIZEDTEXT("", "HasAddIn");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_REFERENCETYPE,
-UA_NODEID_NUMERIC(ns[0], 17604),
-UA_NODEID_NUMERIC(ns[0], 32),
-UA_NODEID_NUMERIC(ns[0], 45),
+UA_NODEID_NUMERIC(ns[0], 17604LU),
+UA_NODEID_NUMERIC(ns[0], 32LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
UA_QUALIFIEDNAME(ns[0], "HasAddIn"),
UA_NODEID_NULL,
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES],NULL, NULL);
@@ -46283,793 +51989,770 @@ return retVal;
static UA_StatusCode function_namespace0_generated_0_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 17604)
-);
-}
-
-/* HasInterface - ns=0;i=17603 */
-
-static UA_StatusCode function_namespace0_generated_1_begin(UA_Server *server, UA_UInt16* ns) {
-UA_StatusCode retVal = UA_STATUSCODE_GOOD;
-UA_ReferenceTypeAttributes attr = UA_ReferenceTypeAttributes_default;
-attr.inverseName = UA_LOCALIZEDTEXT("", "InterfaceOf");
-attr.displayName = UA_LOCALIZEDTEXT("", "HasInterface");
-retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_REFERENCETYPE,
-UA_NODEID_NUMERIC(ns[0], 17603),
-UA_NODEID_NUMERIC(ns[0], 32),
-UA_NODEID_NUMERIC(ns[0], 45),
-UA_QUALIFIEDNAME(ns[0], "HasInterface"),
- UA_NODEID_NULL,
-(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES],NULL, NULL);
-return retVal;
-}
-
-static UA_StatusCode function_namespace0_generated_1_finish(UA_Server *server, UA_UInt16* ns) {
-return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 17603)
+UA_NODEID_NUMERIC(ns[0], 17604LU)
);
}
/* HasHistoricalConfiguration - ns=0;i=56 */
-static UA_StatusCode function_namespace0_generated_2_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_1_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_ReferenceTypeAttributes attr = UA_ReferenceTypeAttributes_default;
attr.inverseName = UA_LOCALIZEDTEXT("", "HistoricalConfigurationOf");
attr.displayName = UA_LOCALIZEDTEXT("", "HasHistoricalConfiguration");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_REFERENCETYPE,
-UA_NODEID_NUMERIC(ns[0], 56),
-UA_NODEID_NUMERIC(ns[0], 44),
-UA_NODEID_NUMERIC(ns[0], 45),
+UA_NODEID_NUMERIC(ns[0], 56LU),
+UA_NODEID_NUMERIC(ns[0], 44LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
UA_QUALIFIEDNAME(ns[0], "HasHistoricalConfiguration"),
UA_NODEID_NULL,
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_2_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_1_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 56)
+UA_NODEID_NUMERIC(ns[0], 56LU)
);
}
/* HasEffect - ns=0;i=54 */
-static UA_StatusCode function_namespace0_generated_3_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_2_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_ReferenceTypeAttributes attr = UA_ReferenceTypeAttributes_default;
attr.inverseName = UA_LOCALIZEDTEXT("", "MayBeEffectedBy");
attr.displayName = UA_LOCALIZEDTEXT("", "HasEffect");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_REFERENCETYPE,
-UA_NODEID_NUMERIC(ns[0], 54),
-UA_NODEID_NUMERIC(ns[0], 32),
-UA_NODEID_NUMERIC(ns[0], 45),
+UA_NODEID_NUMERIC(ns[0], 54LU),
+UA_NODEID_NUMERIC(ns[0], 32LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
UA_QUALIFIEDNAME(ns[0], "HasEffect"),
UA_NODEID_NULL,
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_3_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_2_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 54)
+UA_NODEID_NUMERIC(ns[0], 54LU)
);
}
/* HasCause - ns=0;i=53 */
-static UA_StatusCode function_namespace0_generated_4_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_3_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_ReferenceTypeAttributes attr = UA_ReferenceTypeAttributes_default;
attr.inverseName = UA_LOCALIZEDTEXT("", "MayBeCausedBy");
attr.displayName = UA_LOCALIZEDTEXT("", "HasCause");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_REFERENCETYPE,
-UA_NODEID_NUMERIC(ns[0], 53),
-UA_NODEID_NUMERIC(ns[0], 32),
-UA_NODEID_NUMERIC(ns[0], 45),
+UA_NODEID_NUMERIC(ns[0], 53LU),
+UA_NODEID_NUMERIC(ns[0], 32LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
UA_QUALIFIEDNAME(ns[0], "HasCause"),
UA_NODEID_NULL,
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_4_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_3_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 53)
+UA_NODEID_NUMERIC(ns[0], 53LU)
);
}
/* ToState - ns=0;i=52 */
-static UA_StatusCode function_namespace0_generated_5_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_4_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_ReferenceTypeAttributes attr = UA_ReferenceTypeAttributes_default;
attr.inverseName = UA_LOCALIZEDTEXT("", "FromTransition");
attr.displayName = UA_LOCALIZEDTEXT("", "ToState");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_REFERENCETYPE,
-UA_NODEID_NUMERIC(ns[0], 52),
-UA_NODEID_NUMERIC(ns[0], 32),
-UA_NODEID_NUMERIC(ns[0], 45),
+UA_NODEID_NUMERIC(ns[0], 52LU),
+UA_NODEID_NUMERIC(ns[0], 32LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
UA_QUALIFIEDNAME(ns[0], "ToState"),
UA_NODEID_NULL,
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_5_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_4_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 52)
+UA_NODEID_NUMERIC(ns[0], 52LU)
);
}
/* FromState - ns=0;i=51 */
-static UA_StatusCode function_namespace0_generated_6_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_5_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_ReferenceTypeAttributes attr = UA_ReferenceTypeAttributes_default;
attr.inverseName = UA_LOCALIZEDTEXT("", "ToTransition");
attr.displayName = UA_LOCALIZEDTEXT("", "FromState");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_REFERENCETYPE,
-UA_NODEID_NUMERIC(ns[0], 51),
-UA_NODEID_NUMERIC(ns[0], 32),
-UA_NODEID_NUMERIC(ns[0], 45),
+UA_NODEID_NUMERIC(ns[0], 51LU),
+UA_NODEID_NUMERIC(ns[0], 32LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
UA_QUALIFIEDNAME(ns[0], "FromState"),
UA_NODEID_NULL,
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_6_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_5_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 51)
+UA_NODEID_NUMERIC(ns[0], 51LU)
);
}
/* DiagnosticInfo - ns=0;i=25 */
-static UA_StatusCode function_namespace0_generated_7_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_6_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
attr.displayName = UA_LOCALIZEDTEXT("", "DiagnosticInfo");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_DATATYPE,
-UA_NODEID_NUMERIC(ns[0], 25),
-UA_NODEID_NUMERIC(ns[0], 24),
-UA_NODEID_NUMERIC(ns[0], 45),
+UA_NODEID_NUMERIC(ns[0], 25LU),
+UA_NODEID_NUMERIC(ns[0], 24LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
UA_QUALIFIEDNAME(ns[0], "DiagnosticInfo"),
UA_NODEID_NULL,
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_7_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_6_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 25)
+UA_NODEID_NUMERIC(ns[0], 25LU)
);
}
/* DataValue - ns=0;i=23 */
-static UA_StatusCode function_namespace0_generated_8_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_7_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
attr.displayName = UA_LOCALIZEDTEXT("", "DataValue");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_DATATYPE,
-UA_NODEID_NUMERIC(ns[0], 23),
-UA_NODEID_NUMERIC(ns[0], 24),
-UA_NODEID_NUMERIC(ns[0], 45),
+UA_NODEID_NUMERIC(ns[0], 23LU),
+UA_NODEID_NUMERIC(ns[0], 24LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
UA_QUALIFIEDNAME(ns[0], "DataValue"),
UA_NODEID_NULL,
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_8_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_7_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 23)
+UA_NODEID_NUMERIC(ns[0], 23LU)
);
}
/* Structure - ns=0;i=22 */
-static UA_StatusCode function_namespace0_generated_9_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_8_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
attr.isAbstract = true;
attr.displayName = UA_LOCALIZEDTEXT("", "Structure");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_DATATYPE,
-UA_NODEID_NUMERIC(ns[0], 22),
-UA_NODEID_NUMERIC(ns[0], 24),
-UA_NODEID_NUMERIC(ns[0], 45),
+UA_NODEID_NUMERIC(ns[0], 22LU),
+UA_NODEID_NUMERIC(ns[0], 24LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
UA_QUALIFIEDNAME(ns[0], "Structure"),
UA_NODEID_NULL,
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_9_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_8_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 22)
+UA_NODEID_NUMERIC(ns[0], 22LU)
);
}
-/* ServerStatusDataType - ns=0;i=862 */
+/* TimeZoneDataType - ns=0;i=8912 */
-static UA_StatusCode function_namespace0_generated_10_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_9_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
-attr.displayName = UA_LOCALIZEDTEXT("", "ServerStatusDataType");
+attr.displayName = UA_LOCALIZEDTEXT("", "TimeZoneDataType");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_DATATYPE,
-UA_NODEID_NUMERIC(ns[0], 862),
-UA_NODEID_NUMERIC(ns[0], 22),
-UA_NODEID_NUMERIC(ns[0], 45),
-UA_QUALIFIEDNAME(ns[0], "ServerStatusDataType"),
+UA_NODEID_NUMERIC(ns[0], 8912LU),
+UA_NODEID_NUMERIC(ns[0], 22LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
+UA_QUALIFIEDNAME(ns[0], "TimeZoneDataType"),
UA_NODEID_NULL,
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_10_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_9_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 862)
+UA_NODEID_NUMERIC(ns[0], 8912LU)
);
}
-/* EnumValueType - ns=0;i=7594 */
+/* EUInformation - ns=0;i=887 */
-static UA_StatusCode function_namespace0_generated_11_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_10_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
-attr.displayName = UA_LOCALIZEDTEXT("", "EnumValueType");
+attr.displayName = UA_LOCALIZEDTEXT("", "EUInformation");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_DATATYPE,
-UA_NODEID_NUMERIC(ns[0], 7594),
-UA_NODEID_NUMERIC(ns[0], 22),
-UA_NODEID_NUMERIC(ns[0], 45),
-UA_QUALIFIEDNAME(ns[0], "EnumValueType"),
+UA_NODEID_NUMERIC(ns[0], 887LU),
+UA_NODEID_NUMERIC(ns[0], 22LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
+UA_QUALIFIEDNAME(ns[0], "EUInformation"),
UA_NODEID_NULL,
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_11_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_10_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 7594)
+UA_NODEID_NUMERIC(ns[0], 887LU)
);
}
-/* Union - ns=0;i=12756 */
+/* Range - ns=0;i=884 */
-static UA_StatusCode function_namespace0_generated_12_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_11_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
-attr.isAbstract = true;
-attr.displayName = UA_LOCALIZEDTEXT("", "Union");
+attr.displayName = UA_LOCALIZEDTEXT("", "Range");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_DATATYPE,
-UA_NODEID_NUMERIC(ns[0], 12756),
-UA_NODEID_NUMERIC(ns[0], 22),
-UA_NODEID_NUMERIC(ns[0], 45),
-UA_QUALIFIEDNAME(ns[0], "Union"),
+UA_NODEID_NUMERIC(ns[0], 884LU),
+UA_NODEID_NUMERIC(ns[0], 22LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
+UA_QUALIFIEDNAME(ns[0], "Range"),
UA_NODEID_NULL,
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_12_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_11_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 12756)
+UA_NODEID_NUMERIC(ns[0], 884LU)
);
}
-/* EUInformation - ns=0;i=887 */
+/* ServerStatusDataType - ns=0;i=862 */
-static UA_StatusCode function_namespace0_generated_13_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_12_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
-attr.displayName = UA_LOCALIZEDTEXT("", "EUInformation");
+attr.displayName = UA_LOCALIZEDTEXT("", "ServerStatusDataType");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_DATATYPE,
-UA_NODEID_NUMERIC(ns[0], 887),
-UA_NODEID_NUMERIC(ns[0], 22),
-UA_NODEID_NUMERIC(ns[0], 45),
-UA_QUALIFIEDNAME(ns[0], "EUInformation"),
+UA_NODEID_NUMERIC(ns[0], 862LU),
+UA_NODEID_NUMERIC(ns[0], 22LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
+UA_QUALIFIEDNAME(ns[0], "ServerStatusDataType"),
UA_NODEID_NULL,
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_13_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_12_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 887)
+UA_NODEID_NUMERIC(ns[0], 862LU)
);
}
-/* TimeZoneDataType - ns=0;i=8912 */
+/* EnumValueType - ns=0;i=7594 */
-static UA_StatusCode function_namespace0_generated_14_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_13_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
-attr.displayName = UA_LOCALIZEDTEXT("", "TimeZoneDataType");
+attr.displayName = UA_LOCALIZEDTEXT("", "EnumValueType");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_DATATYPE,
-UA_NODEID_NUMERIC(ns[0], 8912),
-UA_NODEID_NUMERIC(ns[0], 22),
-UA_NODEID_NUMERIC(ns[0], 45),
-UA_QUALIFIEDNAME(ns[0], "TimeZoneDataType"),
+UA_NODEID_NUMERIC(ns[0], 7594LU),
+UA_NODEID_NUMERIC(ns[0], 22LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
+UA_QUALIFIEDNAME(ns[0], "EnumValueType"),
UA_NODEID_NULL,
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_14_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_13_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 8912)
+UA_NODEID_NUMERIC(ns[0], 7594LU)
);
}
/* SignedSoftwareCertificate - ns=0;i=344 */
-static UA_StatusCode function_namespace0_generated_15_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_14_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
attr.displayName = UA_LOCALIZEDTEXT("", "SignedSoftwareCertificate");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_DATATYPE,
-UA_NODEID_NUMERIC(ns[0], 344),
-UA_NODEID_NUMERIC(ns[0], 22),
-UA_NODEID_NUMERIC(ns[0], 45),
+UA_NODEID_NUMERIC(ns[0], 344LU),
+UA_NODEID_NUMERIC(ns[0], 22LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
UA_QUALIFIEDNAME(ns[0], "SignedSoftwareCertificate"),
UA_NODEID_NULL,
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_15_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_14_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 344)
+UA_NODEID_NUMERIC(ns[0], 344LU)
);
}
-/* ServerDiagnosticsSummaryDataType - ns=0;i=859 */
+/* BuildInfo - ns=0;i=338 */
-static UA_StatusCode function_namespace0_generated_16_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_15_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
-attr.displayName = UA_LOCALIZEDTEXT("", "ServerDiagnosticsSummaryDataType");
+attr.displayName = UA_LOCALIZEDTEXT("", "BuildInfo");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_DATATYPE,
-UA_NODEID_NUMERIC(ns[0], 859),
-UA_NODEID_NUMERIC(ns[0], 22),
-UA_NODEID_NUMERIC(ns[0], 45),
-UA_QUALIFIEDNAME(ns[0], "ServerDiagnosticsSummaryDataType"),
+UA_NODEID_NUMERIC(ns[0], 338LU),
+UA_NODEID_NUMERIC(ns[0], 22LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
+UA_QUALIFIEDNAME(ns[0], "BuildInfo"),
UA_NODEID_NULL,
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_16_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_15_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 859)
+UA_NODEID_NUMERIC(ns[0], 338LU)
);
}
/* Argument - ns=0;i=296 */
-static UA_StatusCode function_namespace0_generated_17_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_16_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
attr.displayName = UA_LOCALIZEDTEXT("", "Argument");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_DATATYPE,
-UA_NODEID_NUMERIC(ns[0], 296),
-UA_NODEID_NUMERIC(ns[0], 22),
-UA_NODEID_NUMERIC(ns[0], 45),
+UA_NODEID_NUMERIC(ns[0], 296LU),
+UA_NODEID_NUMERIC(ns[0], 22LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
UA_QUALIFIEDNAME(ns[0], "Argument"),
UA_NODEID_NULL,
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_17_finish(UA_Server *server, UA_UInt16* ns) {
-return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 296)
-);
-}
-
-/* Range - ns=0;i=884 */
-
-static UA_StatusCode function_namespace0_generated_18_begin(UA_Server *server, UA_UInt16* ns) {
-UA_StatusCode retVal = UA_STATUSCODE_GOOD;
-UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
-attr.displayName = UA_LOCALIZEDTEXT("", "Range");
-retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_DATATYPE,
-UA_NODEID_NUMERIC(ns[0], 884),
-UA_NODEID_NUMERIC(ns[0], 22),
-UA_NODEID_NUMERIC(ns[0], 45),
-UA_QUALIFIEDNAME(ns[0], "Range"),
- UA_NODEID_NULL,
-(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
-return retVal;
-}
-
-static UA_StatusCode function_namespace0_generated_18_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_16_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 884)
+UA_NODEID_NUMERIC(ns[0], 296LU)
);
}
-/* BuildInfo - ns=0;i=338 */
+/* Union - ns=0;i=12756 */
-static UA_StatusCode function_namespace0_generated_19_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_17_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
-attr.displayName = UA_LOCALIZEDTEXT("", "BuildInfo");
+attr.isAbstract = true;
+attr.displayName = UA_LOCALIZEDTEXT("", "Union");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_DATATYPE,
-UA_NODEID_NUMERIC(ns[0], 338),
-UA_NODEID_NUMERIC(ns[0], 22),
-UA_NODEID_NUMERIC(ns[0], 45),
-UA_QUALIFIEDNAME(ns[0], "BuildInfo"),
+UA_NODEID_NUMERIC(ns[0], 12756LU),
+UA_NODEID_NUMERIC(ns[0], 22LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
+UA_QUALIFIEDNAME(ns[0], "Union"),
UA_NODEID_NULL,
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_19_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_17_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 338)
+UA_NODEID_NUMERIC(ns[0], 12756LU)
);
}
/* LocalizedText - ns=0;i=21 */
-static UA_StatusCode function_namespace0_generated_20_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_18_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
attr.displayName = UA_LOCALIZEDTEXT("", "LocalizedText");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_DATATYPE,
-UA_NODEID_NUMERIC(ns[0], 21),
-UA_NODEID_NUMERIC(ns[0], 24),
-UA_NODEID_NUMERIC(ns[0], 45),
+UA_NODEID_NUMERIC(ns[0], 21LU),
+UA_NODEID_NUMERIC(ns[0], 24LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
UA_QUALIFIEDNAME(ns[0], "LocalizedText"),
UA_NODEID_NULL,
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_20_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_18_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 21)
+UA_NODEID_NUMERIC(ns[0], 21LU)
);
}
/* QualifiedName - ns=0;i=20 */
-static UA_StatusCode function_namespace0_generated_21_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_19_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
attr.displayName = UA_LOCALIZEDTEXT("", "QualifiedName");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_DATATYPE,
-UA_NODEID_NUMERIC(ns[0], 20),
-UA_NODEID_NUMERIC(ns[0], 24),
-UA_NODEID_NUMERIC(ns[0], 45),
+UA_NODEID_NUMERIC(ns[0], 20LU),
+UA_NODEID_NUMERIC(ns[0], 24LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
UA_QUALIFIEDNAME(ns[0], "QualifiedName"),
UA_NODEID_NULL,
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_21_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_19_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 20)
+UA_NODEID_NUMERIC(ns[0], 20LU)
);
}
/* StatusCode - ns=0;i=19 */
-static UA_StatusCode function_namespace0_generated_22_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_20_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
attr.displayName = UA_LOCALIZEDTEXT("", "StatusCode");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_DATATYPE,
-UA_NODEID_NUMERIC(ns[0], 19),
-UA_NODEID_NUMERIC(ns[0], 24),
-UA_NODEID_NUMERIC(ns[0], 45),
+UA_NODEID_NUMERIC(ns[0], 19LU),
+UA_NODEID_NUMERIC(ns[0], 24LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
UA_QUALIFIEDNAME(ns[0], "StatusCode"),
UA_NODEID_NULL,
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_22_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_20_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 19)
+UA_NODEID_NUMERIC(ns[0], 19LU)
);
}
/* ExpandedNodeId - ns=0;i=18 */
-static UA_StatusCode function_namespace0_generated_23_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_21_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
attr.displayName = UA_LOCALIZEDTEXT("", "ExpandedNodeId");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_DATATYPE,
-UA_NODEID_NUMERIC(ns[0], 18),
-UA_NODEID_NUMERIC(ns[0], 24),
-UA_NODEID_NUMERIC(ns[0], 45),
+UA_NODEID_NUMERIC(ns[0], 18LU),
+UA_NODEID_NUMERIC(ns[0], 24LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
UA_QUALIFIEDNAME(ns[0], "ExpandedNodeId"),
UA_NODEID_NULL,
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_23_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_21_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 18)
+UA_NODEID_NUMERIC(ns[0], 18LU)
);
}
/* NodeId - ns=0;i=17 */
-static UA_StatusCode function_namespace0_generated_24_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_22_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
attr.displayName = UA_LOCALIZEDTEXT("", "NodeId");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_DATATYPE,
-UA_NODEID_NUMERIC(ns[0], 17),
-UA_NODEID_NUMERIC(ns[0], 24),
-UA_NODEID_NUMERIC(ns[0], 45),
+UA_NODEID_NUMERIC(ns[0], 17LU),
+UA_NODEID_NUMERIC(ns[0], 24LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
UA_QUALIFIEDNAME(ns[0], "NodeId"),
UA_NODEID_NULL,
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_24_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_22_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 17)
+UA_NODEID_NUMERIC(ns[0], 17LU)
);
}
/* XmlElement - ns=0;i=16 */
-static UA_StatusCode function_namespace0_generated_25_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_23_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
attr.displayName = UA_LOCALIZEDTEXT("", "XmlElement");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_DATATYPE,
-UA_NODEID_NUMERIC(ns[0], 16),
-UA_NODEID_NUMERIC(ns[0], 24),
-UA_NODEID_NUMERIC(ns[0], 45),
+UA_NODEID_NUMERIC(ns[0], 16LU),
+UA_NODEID_NUMERIC(ns[0], 24LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
UA_QUALIFIEDNAME(ns[0], "XmlElement"),
UA_NODEID_NULL,
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_25_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_23_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 16)
+UA_NODEID_NUMERIC(ns[0], 16LU)
);
}
/* ByteString - ns=0;i=15 */
-static UA_StatusCode function_namespace0_generated_26_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_24_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
attr.displayName = UA_LOCALIZEDTEXT("", "ByteString");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_DATATYPE,
-UA_NODEID_NUMERIC(ns[0], 15),
-UA_NODEID_NUMERIC(ns[0], 24),
-UA_NODEID_NUMERIC(ns[0], 45),
+UA_NODEID_NUMERIC(ns[0], 15LU),
+UA_NODEID_NUMERIC(ns[0], 24LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
UA_QUALIFIEDNAME(ns[0], "ByteString"),
UA_NODEID_NULL,
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_26_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_24_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 15)
+UA_NODEID_NUMERIC(ns[0], 15LU)
);
}
/* Image - ns=0;i=30 */
-static UA_StatusCode function_namespace0_generated_27_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_25_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
attr.isAbstract = true;
attr.displayName = UA_LOCALIZEDTEXT("", "Image");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_DATATYPE,
-UA_NODEID_NUMERIC(ns[0], 30),
-UA_NODEID_NUMERIC(ns[0], 15),
-UA_NODEID_NUMERIC(ns[0], 45),
+UA_NODEID_NUMERIC(ns[0], 30LU),
+UA_NODEID_NUMERIC(ns[0], 15LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
UA_QUALIFIEDNAME(ns[0], "Image"),
UA_NODEID_NULL,
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_27_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_25_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 30)
+UA_NODEID_NUMERIC(ns[0], 30LU)
);
}
/* Guid - ns=0;i=14 */
-static UA_StatusCode function_namespace0_generated_28_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_26_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
attr.displayName = UA_LOCALIZEDTEXT("", "Guid");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_DATATYPE,
-UA_NODEID_NUMERIC(ns[0], 14),
-UA_NODEID_NUMERIC(ns[0], 24),
-UA_NODEID_NUMERIC(ns[0], 45),
+UA_NODEID_NUMERIC(ns[0], 14LU),
+UA_NODEID_NUMERIC(ns[0], 24LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
UA_QUALIFIEDNAME(ns[0], "Guid"),
UA_NODEID_NULL,
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_28_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_26_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 14)
+UA_NODEID_NUMERIC(ns[0], 14LU)
);
}
/* DateTime - ns=0;i=13 */
-static UA_StatusCode function_namespace0_generated_29_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_27_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
attr.displayName = UA_LOCALIZEDTEXT("", "DateTime");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_DATATYPE,
-UA_NODEID_NUMERIC(ns[0], 13),
-UA_NODEID_NUMERIC(ns[0], 24),
-UA_NODEID_NUMERIC(ns[0], 45),
+UA_NODEID_NUMERIC(ns[0], 13LU),
+UA_NODEID_NUMERIC(ns[0], 24LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
UA_QUALIFIEDNAME(ns[0], "DateTime"),
UA_NODEID_NULL,
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_29_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_27_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 13)
+UA_NODEID_NUMERIC(ns[0], 13LU)
);
}
/* UtcTime - ns=0;i=294 */
-static UA_StatusCode function_namespace0_generated_30_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_28_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
attr.displayName = UA_LOCALIZEDTEXT("", "UtcTime");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_DATATYPE,
-UA_NODEID_NUMERIC(ns[0], 294),
-UA_NODEID_NUMERIC(ns[0], 13),
-UA_NODEID_NUMERIC(ns[0], 45),
+UA_NODEID_NUMERIC(ns[0], 294LU),
+UA_NODEID_NUMERIC(ns[0], 13LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
UA_QUALIFIEDNAME(ns[0], "UtcTime"),
UA_NODEID_NULL,
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_30_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_28_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 294)
+UA_NODEID_NUMERIC(ns[0], 294LU)
);
}
/* String - ns=0;i=12 */
-static UA_StatusCode function_namespace0_generated_31_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_29_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
attr.displayName = UA_LOCALIZEDTEXT("", "String");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_DATATYPE,
-UA_NODEID_NUMERIC(ns[0], 12),
-UA_NODEID_NUMERIC(ns[0], 24),
-UA_NODEID_NUMERIC(ns[0], 45),
+UA_NODEID_NUMERIC(ns[0], 12LU),
+UA_NODEID_NUMERIC(ns[0], 24LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
UA_QUALIFIEDNAME(ns[0], "String"),
UA_NODEID_NULL,
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_31_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_29_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 12)
+UA_NODEID_NUMERIC(ns[0], 12LU)
);
}
/* LocaleId - ns=0;i=295 */
-static UA_StatusCode function_namespace0_generated_32_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_30_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
attr.displayName = UA_LOCALIZEDTEXT("", "LocaleId");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_DATATYPE,
-UA_NODEID_NUMERIC(ns[0], 295),
-UA_NODEID_NUMERIC(ns[0], 12),
-UA_NODEID_NUMERIC(ns[0], 45),
+UA_NODEID_NUMERIC(ns[0], 295LU),
+UA_NODEID_NUMERIC(ns[0], 12LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
UA_QUALIFIEDNAME(ns[0], "LocaleId"),
UA_NODEID_NULL,
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_32_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_30_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 295)
+UA_NODEID_NUMERIC(ns[0], 295LU)
);
}
/* Boolean - ns=0;i=1 */
-static UA_StatusCode function_namespace0_generated_33_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_31_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
attr.displayName = UA_LOCALIZEDTEXT("", "Boolean");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_DATATYPE,
-UA_NODEID_NUMERIC(ns[0], 1),
-UA_NODEID_NUMERIC(ns[0], 24),
-UA_NODEID_NUMERIC(ns[0], 45),
+UA_NODEID_NUMERIC(ns[0], 1LU),
+UA_NODEID_NUMERIC(ns[0], 24LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
UA_QUALIFIEDNAME(ns[0], "Boolean"),
UA_NODEID_NULL,
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_33_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_31_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 1)
+UA_NODEID_NUMERIC(ns[0], 1LU)
);
}
/* Enumeration - ns=0;i=29 */
-static UA_StatusCode function_namespace0_generated_34_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_32_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
attr.isAbstract = true;
attr.displayName = UA_LOCALIZEDTEXT("", "Enumeration");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_DATATYPE,
-UA_NODEID_NUMERIC(ns[0], 29),
-UA_NODEID_NUMERIC(ns[0], 24),
-UA_NODEID_NUMERIC(ns[0], 45),
+UA_NODEID_NUMERIC(ns[0], 29LU),
+UA_NODEID_NUMERIC(ns[0], 24LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
UA_QUALIFIEDNAME(ns[0], "Enumeration"),
UA_NODEID_NULL,
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_34_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_32_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 29)
+UA_NODEID_NUMERIC(ns[0], 29LU)
);
}
-/* NamingRuleType - ns=0;i=120 */
+/* ServerState - ns=0;i=852 */
-static UA_StatusCode function_namespace0_generated_35_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_33_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
-attr.displayName = UA_LOCALIZEDTEXT("", "NamingRuleType");
+attr.displayName = UA_LOCALIZEDTEXT("", "ServerState");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_DATATYPE,
-UA_NODEID_NUMERIC(ns[0], 120),
-UA_NODEID_NUMERIC(ns[0], 29),
-UA_NODEID_NUMERIC(ns[0], 45),
-UA_QUALIFIEDNAME(ns[0], "NamingRuleType"),
+UA_NODEID_NUMERIC(ns[0], 852LU),
+UA_NODEID_NUMERIC(ns[0], 29LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
+UA_QUALIFIEDNAME(ns[0], "ServerState"),
UA_NODEID_NULL,
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_35_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_33_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 120)
+UA_NODEID_NUMERIC(ns[0], 852LU)
);
}
-/* EnumValues - ns=0;i=12169 */
+/* RedundancySupport - ns=0;i=851 */
-static UA_StatusCode function_namespace0_generated_36_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_34_begin(UA_Server *server, UA_UInt16* ns) {
+UA_StatusCode retVal = UA_STATUSCODE_GOOD;
+UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
+attr.displayName = UA_LOCALIZEDTEXT("", "RedundancySupport");
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_DATATYPE,
+UA_NODEID_NUMERIC(ns[0], 851LU),
+UA_NODEID_NUMERIC(ns[0], 29LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
+UA_QUALIFIEDNAME(ns[0], "RedundancySupport"),
+ UA_NODEID_NULL,
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
+return retVal;
+}
+
+static UA_StatusCode function_namespace0_generated_34_finish(UA_Server *server, UA_UInt16* ns) {
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 851LU)
+);
+}
+
+/* EnumStrings - ns=0;i=7611 */
+
+static UA_StatusCode function_namespace0_generated_35_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_VariableAttributes attr = UA_VariableAttributes_default;
attr.minimumSamplingInterval = 0.000000;
@@ -47080,69 +52763,57 @@ attr.arrayDimensionsSize = 1;
UA_UInt32 arrayDimensions[1];
arrayDimensions[0] = 0;
attr.arrayDimensions = &arrayDimensions[0];
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 7594);
-UA_EnumValueType variablenode_ns_0_i_12169_variant_DataContents[3];
-
-UA_init(&variablenode_ns_0_i_12169_variant_DataContents[0], &UA_TYPES[UA_TYPES_ENUMVALUETYPE]);
-variablenode_ns_0_i_12169_variant_DataContents[0].value = (UA_Int64) 1;
-variablenode_ns_0_i_12169_variant_DataContents[0].displayName = UA_LOCALIZEDTEXT("", "Mandatory");
-variablenode_ns_0_i_12169_variant_DataContents[0].description = UA_LOCALIZEDTEXT("", "The BrowseName must appear in all instances of the type.");
-
-UA_init(&variablenode_ns_0_i_12169_variant_DataContents[1], &UA_TYPES[UA_TYPES_ENUMVALUETYPE]);
-variablenode_ns_0_i_12169_variant_DataContents[1].value = (UA_Int64) 2;
-variablenode_ns_0_i_12169_variant_DataContents[1].displayName = UA_LOCALIZEDTEXT("", "Optional");
-variablenode_ns_0_i_12169_variant_DataContents[1].description = UA_LOCALIZEDTEXT("", "The BrowseName may appear in an instance of the type.");
-
-UA_init(&variablenode_ns_0_i_12169_variant_DataContents[2], &UA_TYPES[UA_TYPES_ENUMVALUETYPE]);
-variablenode_ns_0_i_12169_variant_DataContents[2].value = (UA_Int64) 3;
-variablenode_ns_0_i_12169_variant_DataContents[2].displayName = UA_LOCALIZEDTEXT("", "Constraint");
-variablenode_ns_0_i_12169_variant_DataContents[2].description = UA_LOCALIZEDTEXT("", "The modelling rule defines a constraint and the BrowseName is not used in an instance of the type.");
-UA_Variant_setArray(&attr.value, &variablenode_ns_0_i_12169_variant_DataContents, (UA_Int32) 3, &UA_TYPES[UA_TYPES_ENUMVALUETYPE]);
-attr.displayName = UA_LOCALIZEDTEXT("", "EnumValues");
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 21LU);
+UA_LocalizedText variablenode_ns_0_i_7611_variant_DataContents[6];
+variablenode_ns_0_i_7611_variant_DataContents[0] = UA_LOCALIZEDTEXT("", "None");
+variablenode_ns_0_i_7611_variant_DataContents[1] = UA_LOCALIZEDTEXT("", "Cold");
+variablenode_ns_0_i_7611_variant_DataContents[2] = UA_LOCALIZEDTEXT("", "Warm");
+variablenode_ns_0_i_7611_variant_DataContents[3] = UA_LOCALIZEDTEXT("", "Hot");
+variablenode_ns_0_i_7611_variant_DataContents[4] = UA_LOCALIZEDTEXT("", "Transparent");
+variablenode_ns_0_i_7611_variant_DataContents[5] = UA_LOCALIZEDTEXT("", "HotAndMirrored");
+UA_Variant_setArray(&attr.value, &variablenode_ns_0_i_7611_variant_DataContents, (UA_Int32) 6, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]);
+attr.displayName = UA_LOCALIZEDTEXT("", "EnumStrings");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 12169),
-UA_NODEID_NUMERIC(ns[0], 120),
-UA_NODEID_NUMERIC(ns[0], 46),
-UA_QUALIFIEDNAME(ns[0], "EnumValues"),
-UA_NODEID_NUMERIC(ns[0], 68),
+UA_NODEID_NUMERIC(ns[0], 7611LU),
+UA_NODEID_NUMERIC(ns[0], 851LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
+UA_QUALIFIEDNAME(ns[0], "EnumStrings"),
+UA_NODEID_NUMERIC(ns[0], 68LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
-
-
-
return retVal;
}
-static UA_StatusCode function_namespace0_generated_36_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_35_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 12169)
+UA_NODEID_NUMERIC(ns[0], 7611LU)
);
}
/* AxisScaleEnumeration - ns=0;i=12077 */
-static UA_StatusCode function_namespace0_generated_37_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_36_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
attr.displayName = UA_LOCALIZEDTEXT("", "AxisScaleEnumeration");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_DATATYPE,
-UA_NODEID_NUMERIC(ns[0], 12077),
-UA_NODEID_NUMERIC(ns[0], 29),
-UA_NODEID_NUMERIC(ns[0], 45),
+UA_NODEID_NUMERIC(ns[0], 12077LU),
+UA_NODEID_NUMERIC(ns[0], 29LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
UA_QUALIFIEDNAME(ns[0], "AxisScaleEnumeration"),
UA_NODEID_NULL,
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_37_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_36_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 12077)
+UA_NODEID_NUMERIC(ns[0], 12077LU)
);
}
/* EnumStrings - ns=0;i=12078 */
-static UA_StatusCode function_namespace0_generated_38_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_37_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_VariableAttributes attr = UA_VariableAttributes_default;
attr.minimumSamplingInterval = 0.000000;
@@ -47153,7 +52824,7 @@ attr.arrayDimensionsSize = 1;
UA_UInt32 arrayDimensions[1];
arrayDimensions[0] = 0;
attr.arrayDimensions = &arrayDimensions[0];
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 21);
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 21LU);
UA_LocalizedText variablenode_ns_0_i_12078_variant_DataContents[3];
variablenode_ns_0_i_12078_variant_DataContents[0] = UA_LOCALIZEDTEXT("", "Linear");
variablenode_ns_0_i_12078_variant_DataContents[1] = UA_LOCALIZEDTEXT("", "Log");
@@ -47161,68 +52832,46 @@ variablenode_ns_0_i_12078_variant_DataContents[2] = UA_LOCALIZEDTEXT("", "Ln");
UA_Variant_setArray(&attr.value, &variablenode_ns_0_i_12078_variant_DataContents, (UA_Int32) 3, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]);
attr.displayName = UA_LOCALIZEDTEXT("", "EnumStrings");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 12078),
-UA_NODEID_NUMERIC(ns[0], 12077),
-UA_NODEID_NUMERIC(ns[0], 46),
+UA_NODEID_NUMERIC(ns[0], 12078LU),
+UA_NODEID_NUMERIC(ns[0], 12077LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
UA_QUALIFIEDNAME(ns[0], "EnumStrings"),
-UA_NODEID_NUMERIC(ns[0], 68),
+UA_NODEID_NUMERIC(ns[0], 68LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_38_finish(UA_Server *server, UA_UInt16* ns) {
-return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 12078)
-);
-}
-
-/* ServerState - ns=0;i=852 */
-
-static UA_StatusCode function_namespace0_generated_39_begin(UA_Server *server, UA_UInt16* ns) {
-UA_StatusCode retVal = UA_STATUSCODE_GOOD;
-UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
-attr.displayName = UA_LOCALIZEDTEXT("", "ServerState");
-retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_DATATYPE,
-UA_NODEID_NUMERIC(ns[0], 852),
-UA_NODEID_NUMERIC(ns[0], 29),
-UA_NODEID_NUMERIC(ns[0], 45),
-UA_QUALIFIEDNAME(ns[0], "ServerState"),
- UA_NODEID_NULL,
-(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
-return retVal;
-}
-
-static UA_StatusCode function_namespace0_generated_39_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_37_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 852)
+UA_NODEID_NUMERIC(ns[0], 12078LU)
);
}
-/* RedundancySupport - ns=0;i=851 */
+/* NamingRuleType - ns=0;i=120 */
-static UA_StatusCode function_namespace0_generated_40_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_38_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
-attr.displayName = UA_LOCALIZEDTEXT("", "RedundancySupport");
+attr.displayName = UA_LOCALIZEDTEXT("", "NamingRuleType");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_DATATYPE,
-UA_NODEID_NUMERIC(ns[0], 851),
-UA_NODEID_NUMERIC(ns[0], 29),
-UA_NODEID_NUMERIC(ns[0], 45),
-UA_QUALIFIEDNAME(ns[0], "RedundancySupport"),
+UA_NODEID_NUMERIC(ns[0], 120LU),
+UA_NODEID_NUMERIC(ns[0], 29LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
+UA_QUALIFIEDNAME(ns[0], "NamingRuleType"),
UA_NODEID_NULL,
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_40_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_38_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 851)
+UA_NODEID_NUMERIC(ns[0], 120LU)
);
}
-/* EnumStrings - ns=0;i=7611 */
+/* EnumValues - ns=0;i=12169 */
-static UA_StatusCode function_namespace0_generated_41_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_39_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_VariableAttributes attr = UA_VariableAttributes_default;
attr.minimumSamplingInterval = 0.000000;
@@ -47233,613 +52882,621 @@ attr.arrayDimensionsSize = 1;
UA_UInt32 arrayDimensions[1];
arrayDimensions[0] = 0;
attr.arrayDimensions = &arrayDimensions[0];
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 21);
-UA_LocalizedText variablenode_ns_0_i_7611_variant_DataContents[6];
-variablenode_ns_0_i_7611_variant_DataContents[0] = UA_LOCALIZEDTEXT("", "None");
-variablenode_ns_0_i_7611_variant_DataContents[1] = UA_LOCALIZEDTEXT("", "Cold");
-variablenode_ns_0_i_7611_variant_DataContents[2] = UA_LOCALIZEDTEXT("", "Warm");
-variablenode_ns_0_i_7611_variant_DataContents[3] = UA_LOCALIZEDTEXT("", "Hot");
-variablenode_ns_0_i_7611_variant_DataContents[4] = UA_LOCALIZEDTEXT("", "Transparent");
-variablenode_ns_0_i_7611_variant_DataContents[5] = UA_LOCALIZEDTEXT("", "HotAndMirrored");
-UA_Variant_setArray(&attr.value, &variablenode_ns_0_i_7611_variant_DataContents, (UA_Int32) 6, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]);
-attr.displayName = UA_LOCALIZEDTEXT("", "EnumStrings");
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 7594LU);
+UA_EnumValueType variablenode_ns_0_i_12169_variant_DataContents[3];
+
+UA_init(&variablenode_ns_0_i_12169_variant_DataContents[0], &UA_TYPES[UA_TYPES_ENUMVALUETYPE]);
+variablenode_ns_0_i_12169_variant_DataContents[0].value = (UA_Int64) 1;
+variablenode_ns_0_i_12169_variant_DataContents[0].displayName = UA_LOCALIZEDTEXT("", "Mandatory");
+variablenode_ns_0_i_12169_variant_DataContents[0].description = UA_LOCALIZEDTEXT("", "The BrowseName must appear in all instances of the type.");
+
+UA_init(&variablenode_ns_0_i_12169_variant_DataContents[1], &UA_TYPES[UA_TYPES_ENUMVALUETYPE]);
+variablenode_ns_0_i_12169_variant_DataContents[1].value = (UA_Int64) 2;
+variablenode_ns_0_i_12169_variant_DataContents[1].displayName = UA_LOCALIZEDTEXT("", "Optional");
+variablenode_ns_0_i_12169_variant_DataContents[1].description = UA_LOCALIZEDTEXT("", "The BrowseName may appear in an instance of the type.");
+
+UA_init(&variablenode_ns_0_i_12169_variant_DataContents[2], &UA_TYPES[UA_TYPES_ENUMVALUETYPE]);
+variablenode_ns_0_i_12169_variant_DataContents[2].value = (UA_Int64) 3;
+variablenode_ns_0_i_12169_variant_DataContents[2].displayName = UA_LOCALIZEDTEXT("", "Constraint");
+variablenode_ns_0_i_12169_variant_DataContents[2].description = UA_LOCALIZEDTEXT("", "The modelling rule defines a constraint and the BrowseName is not used in an instance of the type.");
+UA_Variant_setArray(&attr.value, &variablenode_ns_0_i_12169_variant_DataContents, (UA_Int32) 3, &UA_TYPES[UA_TYPES_ENUMVALUETYPE]);
+attr.displayName = UA_LOCALIZEDTEXT("", "EnumValues");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 7611),
-UA_NODEID_NUMERIC(ns[0], 851),
-UA_NODEID_NUMERIC(ns[0], 46),
-UA_QUALIFIEDNAME(ns[0], "EnumStrings"),
-UA_NODEID_NUMERIC(ns[0], 68),
+UA_NODEID_NUMERIC(ns[0], 12169LU),
+UA_NODEID_NUMERIC(ns[0], 120LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
+UA_QUALIFIEDNAME(ns[0], "EnumValues"),
+UA_NODEID_NUMERIC(ns[0], 68LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+
+
+
return retVal;
}
-static UA_StatusCode function_namespace0_generated_41_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_39_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 7611)
+UA_NODEID_NUMERIC(ns[0], 12169LU)
);
}
/* Number - ns=0;i=26 */
-static UA_StatusCode function_namespace0_generated_42_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_40_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
attr.isAbstract = true;
attr.displayName = UA_LOCALIZEDTEXT("", "Number");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_DATATYPE,
-UA_NODEID_NUMERIC(ns[0], 26),
-UA_NODEID_NUMERIC(ns[0], 24),
-UA_NODEID_NUMERIC(ns[0], 45),
+UA_NODEID_NUMERIC(ns[0], 26LU),
+UA_NODEID_NUMERIC(ns[0], 24LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
UA_QUALIFIEDNAME(ns[0], "Number"),
UA_NODEID_NULL,
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_42_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_40_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 26)
+UA_NODEID_NUMERIC(ns[0], 26LU)
);
}
-/* UInteger - ns=0;i=28 */
+/* Decimal - ns=0;i=50 */
-static UA_StatusCode function_namespace0_generated_43_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_41_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
-attr.isAbstract = true;
-attr.displayName = UA_LOCALIZEDTEXT("", "UInteger");
+attr.displayName = UA_LOCALIZEDTEXT("", "Decimal");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_DATATYPE,
-UA_NODEID_NUMERIC(ns[0], 28),
-UA_NODEID_NUMERIC(ns[0], 26),
-UA_NODEID_NUMERIC(ns[0], 45),
-UA_QUALIFIEDNAME(ns[0], "UInteger"),
+UA_NODEID_NUMERIC(ns[0], 50LU),
+UA_NODEID_NUMERIC(ns[0], 26LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
+UA_QUALIFIEDNAME(ns[0], "Decimal"),
UA_NODEID_NULL,
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_43_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_41_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 28)
+UA_NODEID_NUMERIC(ns[0], 50LU)
);
}
-/* UInt64 - ns=0;i=9 */
+/* UInteger - ns=0;i=28 */
-static UA_StatusCode function_namespace0_generated_44_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_42_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
-attr.displayName = UA_LOCALIZEDTEXT("", "UInt64");
+attr.isAbstract = true;
+attr.displayName = UA_LOCALIZEDTEXT("", "UInteger");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_DATATYPE,
-UA_NODEID_NUMERIC(ns[0], 9),
-UA_NODEID_NUMERIC(ns[0], 28),
-UA_NODEID_NUMERIC(ns[0], 45),
-UA_QUALIFIEDNAME(ns[0], "UInt64"),
+UA_NODEID_NUMERIC(ns[0], 28LU),
+UA_NODEID_NUMERIC(ns[0], 26LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
+UA_QUALIFIEDNAME(ns[0], "UInteger"),
UA_NODEID_NULL,
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_44_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_42_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 9)
+UA_NODEID_NUMERIC(ns[0], 28LU)
);
}
-/* Byte - ns=0;i=3 */
+/* UInt64 - ns=0;i=9 */
-static UA_StatusCode function_namespace0_generated_45_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_43_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
-attr.displayName = UA_LOCALIZEDTEXT("", "Byte");
+attr.displayName = UA_LOCALIZEDTEXT("", "UInt64");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_DATATYPE,
-UA_NODEID_NUMERIC(ns[0], 3),
-UA_NODEID_NUMERIC(ns[0], 28),
-UA_NODEID_NUMERIC(ns[0], 45),
-UA_QUALIFIEDNAME(ns[0], "Byte"),
+UA_NODEID_NUMERIC(ns[0], 9LU),
+UA_NODEID_NUMERIC(ns[0], 28LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
+UA_QUALIFIEDNAME(ns[0], "UInt64"),
UA_NODEID_NULL,
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_45_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_43_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 3)
+UA_NODEID_NUMERIC(ns[0], 9LU)
);
}
/* UInt32 - ns=0;i=7 */
-static UA_StatusCode function_namespace0_generated_46_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_44_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
attr.displayName = UA_LOCALIZEDTEXT("", "UInt32");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_DATATYPE,
-UA_NODEID_NUMERIC(ns[0], 7),
-UA_NODEID_NUMERIC(ns[0], 28),
-UA_NODEID_NUMERIC(ns[0], 45),
+UA_NODEID_NUMERIC(ns[0], 7LU),
+UA_NODEID_NUMERIC(ns[0], 28LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
UA_QUALIFIEDNAME(ns[0], "UInt32"),
UA_NODEID_NULL,
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_46_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_44_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 7)
+UA_NODEID_NUMERIC(ns[0], 7LU)
);
}
/* UInt16 - ns=0;i=5 */
-static UA_StatusCode function_namespace0_generated_47_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_45_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
attr.displayName = UA_LOCALIZEDTEXT("", "UInt16");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_DATATYPE,
-UA_NODEID_NUMERIC(ns[0], 5),
-UA_NODEID_NUMERIC(ns[0], 28),
-UA_NODEID_NUMERIC(ns[0], 45),
+UA_NODEID_NUMERIC(ns[0], 5LU),
+UA_NODEID_NUMERIC(ns[0], 28LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
UA_QUALIFIEDNAME(ns[0], "UInt16"),
UA_NODEID_NULL,
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_47_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_45_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 5)
+UA_NODEID_NUMERIC(ns[0], 5LU)
);
}
-/* Integer - ns=0;i=27 */
+/* Byte - ns=0;i=3 */
-static UA_StatusCode function_namespace0_generated_48_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_46_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
-attr.isAbstract = true;
-attr.displayName = UA_LOCALIZEDTEXT("", "Integer");
+attr.displayName = UA_LOCALIZEDTEXT("", "Byte");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_DATATYPE,
-UA_NODEID_NUMERIC(ns[0], 27),
-UA_NODEID_NUMERIC(ns[0], 26),
-UA_NODEID_NUMERIC(ns[0], 45),
-UA_QUALIFIEDNAME(ns[0], "Integer"),
+UA_NODEID_NUMERIC(ns[0], 3LU),
+UA_NODEID_NUMERIC(ns[0], 28LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
+UA_QUALIFIEDNAME(ns[0], "Byte"),
UA_NODEID_NULL,
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_48_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_46_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 27)
+UA_NODEID_NUMERIC(ns[0], 3LU)
);
}
-/* Int16 - ns=0;i=4 */
+/* Integer - ns=0;i=27 */
-static UA_StatusCode function_namespace0_generated_49_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_47_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
-attr.displayName = UA_LOCALIZEDTEXT("", "Int16");
+attr.isAbstract = true;
+attr.displayName = UA_LOCALIZEDTEXT("", "Integer");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_DATATYPE,
-UA_NODEID_NUMERIC(ns[0], 4),
-UA_NODEID_NUMERIC(ns[0], 27),
-UA_NODEID_NUMERIC(ns[0], 45),
-UA_QUALIFIEDNAME(ns[0], "Int16"),
+UA_NODEID_NUMERIC(ns[0], 27LU),
+UA_NODEID_NUMERIC(ns[0], 26LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
+UA_QUALIFIEDNAME(ns[0], "Integer"),
UA_NODEID_NULL,
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_49_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_47_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 4)
+UA_NODEID_NUMERIC(ns[0], 27LU)
);
}
-/* Int32 - ns=0;i=6 */
+/* Int64 - ns=0;i=8 */
-static UA_StatusCode function_namespace0_generated_50_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_48_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
-attr.displayName = UA_LOCALIZEDTEXT("", "Int32");
+attr.displayName = UA_LOCALIZEDTEXT("", "Int64");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_DATATYPE,
-UA_NODEID_NUMERIC(ns[0], 6),
-UA_NODEID_NUMERIC(ns[0], 27),
-UA_NODEID_NUMERIC(ns[0], 45),
-UA_QUALIFIEDNAME(ns[0], "Int32"),
+UA_NODEID_NUMERIC(ns[0], 8LU),
+UA_NODEID_NUMERIC(ns[0], 27LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
+UA_QUALIFIEDNAME(ns[0], "Int64"),
UA_NODEID_NULL,
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_50_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_48_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 6)
+UA_NODEID_NUMERIC(ns[0], 8LU)
);
}
-/* Int64 - ns=0;i=8 */
+/* Int32 - ns=0;i=6 */
-static UA_StatusCode function_namespace0_generated_51_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_49_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
-attr.displayName = UA_LOCALIZEDTEXT("", "Int64");
+attr.displayName = UA_LOCALIZEDTEXT("", "Int32");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_DATATYPE,
-UA_NODEID_NUMERIC(ns[0], 8),
-UA_NODEID_NUMERIC(ns[0], 27),
-UA_NODEID_NUMERIC(ns[0], 45),
-UA_QUALIFIEDNAME(ns[0], "Int64"),
+UA_NODEID_NUMERIC(ns[0], 6LU),
+UA_NODEID_NUMERIC(ns[0], 27LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
+UA_QUALIFIEDNAME(ns[0], "Int32"),
UA_NODEID_NULL,
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_51_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_49_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 8)
+UA_NODEID_NUMERIC(ns[0], 6LU)
);
}
-/* SByte - ns=0;i=2 */
+/* Int16 - ns=0;i=4 */
-static UA_StatusCode function_namespace0_generated_52_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_50_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
-attr.displayName = UA_LOCALIZEDTEXT("", "SByte");
+attr.displayName = UA_LOCALIZEDTEXT("", "Int16");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_DATATYPE,
-UA_NODEID_NUMERIC(ns[0], 2),
-UA_NODEID_NUMERIC(ns[0], 27),
-UA_NODEID_NUMERIC(ns[0], 45),
-UA_QUALIFIEDNAME(ns[0], "SByte"),
+UA_NODEID_NUMERIC(ns[0], 4LU),
+UA_NODEID_NUMERIC(ns[0], 27LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
+UA_QUALIFIEDNAME(ns[0], "Int16"),
UA_NODEID_NULL,
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_52_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_50_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2)
+UA_NODEID_NUMERIC(ns[0], 4LU)
);
}
-/* Float - ns=0;i=10 */
+/* SByte - ns=0;i=2 */
-static UA_StatusCode function_namespace0_generated_53_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_51_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
-attr.displayName = UA_LOCALIZEDTEXT("", "Float");
+attr.displayName = UA_LOCALIZEDTEXT("", "SByte");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_DATATYPE,
-UA_NODEID_NUMERIC(ns[0], 10),
-UA_NODEID_NUMERIC(ns[0], 26),
-UA_NODEID_NUMERIC(ns[0], 45),
-UA_QUALIFIEDNAME(ns[0], "Float"),
+UA_NODEID_NUMERIC(ns[0], 2LU),
+UA_NODEID_NUMERIC(ns[0], 27LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
+UA_QUALIFIEDNAME(ns[0], "SByte"),
UA_NODEID_NULL,
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_53_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_51_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 10)
+UA_NODEID_NUMERIC(ns[0], 2LU)
);
}
-/* Decimal - ns=0;i=50 */
+/* Double - ns=0;i=11 */
-static UA_StatusCode function_namespace0_generated_54_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_52_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
-attr.displayName = UA_LOCALIZEDTEXT("", "Decimal");
+attr.displayName = UA_LOCALIZEDTEXT("", "Double");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_DATATYPE,
-UA_NODEID_NUMERIC(ns[0], 50),
-UA_NODEID_NUMERIC(ns[0], 26),
-UA_NODEID_NUMERIC(ns[0], 45),
-UA_QUALIFIEDNAME(ns[0], "Decimal"),
+UA_NODEID_NUMERIC(ns[0], 11LU),
+UA_NODEID_NUMERIC(ns[0], 26LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
+UA_QUALIFIEDNAME(ns[0], "Double"),
UA_NODEID_NULL,
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_54_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_52_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 50)
+UA_NODEID_NUMERIC(ns[0], 11LU)
);
}
-/* Double - ns=0;i=11 */
+/* Duration - ns=0;i=290 */
-static UA_StatusCode function_namespace0_generated_55_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_53_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
-attr.displayName = UA_LOCALIZEDTEXT("", "Double");
+attr.displayName = UA_LOCALIZEDTEXT("", "Duration");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_DATATYPE,
-UA_NODEID_NUMERIC(ns[0], 11),
-UA_NODEID_NUMERIC(ns[0], 26),
-UA_NODEID_NUMERIC(ns[0], 45),
-UA_QUALIFIEDNAME(ns[0], "Double"),
+UA_NODEID_NUMERIC(ns[0], 290LU),
+UA_NODEID_NUMERIC(ns[0], 11LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
+UA_QUALIFIEDNAME(ns[0], "Duration"),
UA_NODEID_NULL,
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_55_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_53_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 11)
+UA_NODEID_NUMERIC(ns[0], 290LU)
);
}
-/* Duration - ns=0;i=290 */
+/* Float - ns=0;i=10 */
-static UA_StatusCode function_namespace0_generated_56_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_54_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
-attr.displayName = UA_LOCALIZEDTEXT("", "Duration");
+attr.displayName = UA_LOCALIZEDTEXT("", "Float");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_DATATYPE,
-UA_NODEID_NUMERIC(ns[0], 290),
-UA_NODEID_NUMERIC(ns[0], 11),
-UA_NODEID_NUMERIC(ns[0], 45),
-UA_QUALIFIEDNAME(ns[0], "Duration"),
+UA_NODEID_NUMERIC(ns[0], 10LU),
+UA_NODEID_NUMERIC(ns[0], 26LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
+UA_QUALIFIEDNAME(ns[0], "Float"),
UA_NODEID_NULL,
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_56_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_54_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 290)
+UA_NODEID_NUMERIC(ns[0], 10LU)
);
}
/* DataItemType - ns=0;i=2365 */
-static UA_StatusCode function_namespace0_generated_57_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_55_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_VariableTypeAttributes attr = UA_VariableTypeAttributes_default;
attr.valueRank = -2;
/* DataType inherited */
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 24);
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 24LU);
attr.displayName = UA_LOCALIZEDTEXT("", "DataItemType");
#ifdef UA_ENABLE_NODESET_COMPILER_DESCRIPTIONS
attr.description = UA_LOCALIZEDTEXT("", "A variable that contains live automation data.");
#endif
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLETYPE,
-UA_NODEID_NUMERIC(ns[0], 2365),
-UA_NODEID_NUMERIC(ns[0], 63),
-UA_NODEID_NUMERIC(ns[0], 45),
+UA_NODEID_NUMERIC(ns[0], 2365LU),
+UA_NODEID_NUMERIC(ns[0], 63LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
UA_QUALIFIEDNAME(ns[0], "DataItemType"),
-UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_57_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_55_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2365)
+UA_NODEID_NUMERIC(ns[0], 2365LU)
);
}
-/* AnalogItemType - ns=0;i=2368 */
+/* DiscreteItemType - ns=0;i=2372 */
-static UA_StatusCode function_namespace0_generated_58_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_56_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_VariableTypeAttributes attr = UA_VariableTypeAttributes_default;
+attr.isAbstract = true;
attr.valueRank = -2;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 26);
-attr.displayName = UA_LOCALIZEDTEXT("", "AnalogItemType");
+/* DataType inherited */
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 24LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "DiscreteItemType");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLETYPE,
-UA_NODEID_NUMERIC(ns[0], 2368),
-UA_NODEID_NUMERIC(ns[0], 2365),
-UA_NODEID_NUMERIC(ns[0], 45),
-UA_QUALIFIEDNAME(ns[0], "AnalogItemType"),
-UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 2372LU),
+UA_NODEID_NUMERIC(ns[0], 2365LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
+UA_QUALIFIEDNAME(ns[0], "DiscreteItemType"),
+UA_NODEID_NUMERIC(ns[0], 0LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_58_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_56_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2368)
+UA_NODEID_NUMERIC(ns[0], 2372LU)
);
}
-/* InstrumentRange - ns=0;i=2370 */
+/* MultiStateDiscreteType - ns=0;i=2376 */
-static UA_StatusCode function_namespace0_generated_59_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_57_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
-UA_VariableAttributes attr = UA_VariableAttributes_default;
-attr.minimumSamplingInterval = 0.000000;
-attr.userAccessLevel = 1;
-attr.accessLevel = 1;
-/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 884);
-attr.displayName = UA_LOCALIZEDTEXT("", "InstrumentRange");
-retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 2370),
-UA_NODEID_NUMERIC(ns[0], 2368),
-UA_NODEID_NUMERIC(ns[0], 46),
-UA_QUALIFIEDNAME(ns[0], "InstrumentRange"),
-UA_NODEID_NUMERIC(ns[0], 68),
-(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+UA_VariableTypeAttributes attr = UA_VariableTypeAttributes_default;
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 28LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "MultiStateDiscreteType");
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLETYPE,
+UA_NODEID_NUMERIC(ns[0], 2376LU),
+UA_NODEID_NUMERIC(ns[0], 2372LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
+UA_QUALIFIEDNAME(ns[0], "MultiStateDiscreteType"),
+UA_NODEID_NUMERIC(ns[0], 0LU),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_59_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_57_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2370)
+UA_NODEID_NUMERIC(ns[0], 2376LU)
);
}
-/* EngineeringUnits - ns=0;i=2371 */
+/* EnumStrings - ns=0;i=2377 */
-static UA_StatusCode function_namespace0_generated_60_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_58_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_VariableAttributes attr = UA_VariableAttributes_default;
attr.minimumSamplingInterval = 0.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
-/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 887);
-attr.displayName = UA_LOCALIZEDTEXT("", "EngineeringUnits");
+attr.valueRank = 1;
+attr.arrayDimensionsSize = 1;
+UA_UInt32 arrayDimensions[1];
+arrayDimensions[0] = 0;
+attr.arrayDimensions = &arrayDimensions[0];
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 21LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "EnumStrings");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 2371),
-UA_NODEID_NUMERIC(ns[0], 2368),
-UA_NODEID_NUMERIC(ns[0], 46),
-UA_QUALIFIEDNAME(ns[0], "EngineeringUnits"),
-UA_NODEID_NUMERIC(ns[0], 68),
+UA_NODEID_NUMERIC(ns[0], 2377LU),
+UA_NODEID_NUMERIC(ns[0], 2376LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
+UA_QUALIFIEDNAME(ns[0], "EnumStrings"),
+UA_NODEID_NUMERIC(ns[0], 68LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_60_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_58_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2371)
+UA_NODEID_NUMERIC(ns[0], 2377LU)
);
}
-/* EURange - ns=0;i=2369 */
+/* TwoStateDiscreteType - ns=0;i=2373 */
-static UA_StatusCode function_namespace0_generated_61_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_59_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
-UA_VariableAttributes attr = UA_VariableAttributes_default;
-attr.minimumSamplingInterval = 0.000000;
-attr.userAccessLevel = 3;
-attr.accessLevel = 3;
-/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 884);
-attr.displayName = UA_LOCALIZEDTEXT("", "EURange");
-retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 2369),
-UA_NODEID_NUMERIC(ns[0], 2368),
-UA_NODEID_NUMERIC(ns[0], 46),
-UA_QUALIFIEDNAME(ns[0], "EURange"),
-UA_NODEID_NUMERIC(ns[0], 68),
-(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+UA_VariableTypeAttributes attr = UA_VariableTypeAttributes_default;
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 1LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "TwoStateDiscreteType");
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLETYPE,
+UA_NODEID_NUMERIC(ns[0], 2373LU),
+UA_NODEID_NUMERIC(ns[0], 2372LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
+UA_QUALIFIEDNAME(ns[0], "TwoStateDiscreteType"),
+UA_NODEID_NUMERIC(ns[0], 0LU),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_61_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_59_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2369)
+UA_NODEID_NUMERIC(ns[0], 2373LU)
);
}
-/* ValuePrecision - ns=0;i=2367 */
+/* TrueState - ns=0;i=2375 */
-static UA_StatusCode function_namespace0_generated_62_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_60_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_VariableAttributes attr = UA_VariableAttributes_default;
attr.minimumSamplingInterval = 0.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 11);
-attr.displayName = UA_LOCALIZEDTEXT("", "ValuePrecision");
-#ifdef UA_ENABLE_NODESET_COMPILER_DESCRIPTIONS
-attr.description = UA_LOCALIZEDTEXT("", "The maximum precision that the server can maintain for the item based on restrictions in the target environment.");
-#endif
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 21LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "TrueState");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 2367),
-UA_NODEID_NUMERIC(ns[0], 2365),
-UA_NODEID_NUMERIC(ns[0], 46),
-UA_QUALIFIEDNAME(ns[0], "ValuePrecision"),
-UA_NODEID_NUMERIC(ns[0], 68),
+UA_NODEID_NUMERIC(ns[0], 2375LU),
+UA_NODEID_NUMERIC(ns[0], 2373LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
+UA_QUALIFIEDNAME(ns[0], "TrueState"),
+UA_NODEID_NUMERIC(ns[0], 68LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_62_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_60_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2367)
+UA_NODEID_NUMERIC(ns[0], 2375LU)
);
}
-/* DiscreteItemType - ns=0;i=2372 */
+/* FalseState - ns=0;i=2374 */
-static UA_StatusCode function_namespace0_generated_63_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_61_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
-UA_VariableTypeAttributes attr = UA_VariableTypeAttributes_default;
-attr.isAbstract = true;
+UA_VariableAttributes attr = UA_VariableAttributes_default;
+attr.minimumSamplingInterval = 0.000000;
+attr.userAccessLevel = 1;
+attr.accessLevel = 1;
+/* Value rank inherited */
attr.valueRank = -2;
-/* DataType inherited */
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 24);
-attr.displayName = UA_LOCALIZEDTEXT("", "DiscreteItemType");
-retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLETYPE,
-UA_NODEID_NUMERIC(ns[0], 2372),
-UA_NODEID_NUMERIC(ns[0], 2365),
-UA_NODEID_NUMERIC(ns[0], 45),
-UA_QUALIFIEDNAME(ns[0], "DiscreteItemType"),
-UA_NODEID_NUMERIC(ns[0], 0),
-(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES],NULL, NULL);
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 21LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "FalseState");
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 2374LU),
+UA_NODEID_NUMERIC(ns[0], 2373LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
+UA_QUALIFIEDNAME(ns[0], "FalseState"),
+UA_NODEID_NUMERIC(ns[0], 68LU),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_63_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_61_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2372)
+UA_NODEID_NUMERIC(ns[0], 2374LU)
);
}
/* MultiStateValueDiscreteType - ns=0;i=11238 */
-static UA_StatusCode function_namespace0_generated_64_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_62_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_VariableTypeAttributes attr = UA_VariableTypeAttributes_default;
attr.valueRank = -2;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 26);
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 26LU);
attr.displayName = UA_LOCALIZEDTEXT("", "MultiStateValueDiscreteType");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLETYPE,
-UA_NODEID_NUMERIC(ns[0], 11238),
-UA_NODEID_NUMERIC(ns[0], 2372),
-UA_NODEID_NUMERIC(ns[0], 45),
+UA_NODEID_NUMERIC(ns[0], 11238LU),
+UA_NODEID_NUMERIC(ns[0], 2372LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
UA_QUALIFIEDNAME(ns[0], "MultiStateValueDiscreteType"),
-UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_64_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_62_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 11238)
+UA_NODEID_NUMERIC(ns[0], 11238LU)
);
}
/* ValueAsText - ns=0;i=11461 */
-static UA_StatusCode function_namespace0_generated_65_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_63_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_VariableAttributes attr = UA_VariableAttributes_default;
attr.minimumSamplingInterval = 0.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 21);
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 21LU);
attr.displayName = UA_LOCALIZEDTEXT("", "ValueAsText");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 11461),
-UA_NODEID_NUMERIC(ns[0], 11238),
-UA_NODEID_NUMERIC(ns[0], 46),
+UA_NODEID_NUMERIC(ns[0], 11461LU),
+UA_NODEID_NUMERIC(ns[0], 11238LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
UA_QUALIFIEDNAME(ns[0], "ValueAsText"),
-UA_NODEID_NUMERIC(ns[0], 68),
+UA_NODEID_NUMERIC(ns[0], 68LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_65_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_63_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 11461)
+UA_NODEID_NUMERIC(ns[0], 11461LU)
);
}
/* EnumValues - ns=0;i=11241 */
-static UA_StatusCode function_namespace0_generated_66_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_64_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_VariableAttributes attr = UA_VariableAttributes_default;
attr.minimumSamplingInterval = 0.000000;
@@ -47850,586 +53507,637 @@ attr.arrayDimensionsSize = 1;
UA_UInt32 arrayDimensions[1];
arrayDimensions[0] = 0;
attr.arrayDimensions = &arrayDimensions[0];
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 7594);
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 7594LU);
attr.displayName = UA_LOCALIZEDTEXT("", "EnumValues");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 11241),
-UA_NODEID_NUMERIC(ns[0], 11238),
-UA_NODEID_NUMERIC(ns[0], 46),
+UA_NODEID_NUMERIC(ns[0], 11241LU),
+UA_NODEID_NUMERIC(ns[0], 11238LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
UA_QUALIFIEDNAME(ns[0], "EnumValues"),
-UA_NODEID_NUMERIC(ns[0], 68),
+UA_NODEID_NUMERIC(ns[0], 68LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_66_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_64_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 11241)
+UA_NODEID_NUMERIC(ns[0], 11241LU)
);
}
-/* MultiStateDiscreteType - ns=0;i=2376 */
+/* AnalogItemType - ns=0;i=2368 */
-static UA_StatusCode function_namespace0_generated_67_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_65_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_VariableTypeAttributes attr = UA_VariableTypeAttributes_default;
attr.valueRank = -2;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 28);
-attr.displayName = UA_LOCALIZEDTEXT("", "MultiStateDiscreteType");
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 26LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "AnalogItemType");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLETYPE,
-UA_NODEID_NUMERIC(ns[0], 2376),
-UA_NODEID_NUMERIC(ns[0], 2372),
-UA_NODEID_NUMERIC(ns[0], 45),
-UA_QUALIFIEDNAME(ns[0], "MultiStateDiscreteType"),
-UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 2368LU),
+UA_NODEID_NUMERIC(ns[0], 2365LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
+UA_QUALIFIEDNAME(ns[0], "AnalogItemType"),
+UA_NODEID_NUMERIC(ns[0], 0LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_67_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_65_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2376)
+UA_NODEID_NUMERIC(ns[0], 2368LU)
);
}
-/* EnumStrings - ns=0;i=2377 */
+/* EngineeringUnits - ns=0;i=2371 */
-static UA_StatusCode function_namespace0_generated_68_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_66_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_VariableAttributes attr = UA_VariableAttributes_default;
attr.minimumSamplingInterval = 0.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
-attr.valueRank = 1;
-attr.arrayDimensionsSize = 1;
-UA_UInt32 arrayDimensions[1];
-arrayDimensions[0] = 0;
-attr.arrayDimensions = &arrayDimensions[0];
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 21);
-attr.displayName = UA_LOCALIZEDTEXT("", "EnumStrings");
+/* Value rank inherited */
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 887LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "EngineeringUnits");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 2377),
-UA_NODEID_NUMERIC(ns[0], 2376),
-UA_NODEID_NUMERIC(ns[0], 46),
-UA_QUALIFIEDNAME(ns[0], "EnumStrings"),
-UA_NODEID_NUMERIC(ns[0], 68),
+UA_NODEID_NUMERIC(ns[0], 2371LU),
+UA_NODEID_NUMERIC(ns[0], 2368LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
+UA_QUALIFIEDNAME(ns[0], "EngineeringUnits"),
+UA_NODEID_NUMERIC(ns[0], 68LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_68_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_66_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2377)
+UA_NODEID_NUMERIC(ns[0], 2371LU)
);
}
-/* TwoStateDiscreteType - ns=0;i=2373 */
+/* InstrumentRange - ns=0;i=2370 */
-static UA_StatusCode function_namespace0_generated_69_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_67_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
-UA_VariableTypeAttributes attr = UA_VariableTypeAttributes_default;
+UA_VariableAttributes attr = UA_VariableAttributes_default;
+attr.minimumSamplingInterval = 0.000000;
+attr.userAccessLevel = 1;
+attr.accessLevel = 1;
+/* Value rank inherited */
attr.valueRank = -2;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 1);
-attr.displayName = UA_LOCALIZEDTEXT("", "TwoStateDiscreteType");
-retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLETYPE,
-UA_NODEID_NUMERIC(ns[0], 2373),
-UA_NODEID_NUMERIC(ns[0], 2372),
-UA_NODEID_NUMERIC(ns[0], 45),
-UA_QUALIFIEDNAME(ns[0], "TwoStateDiscreteType"),
-UA_NODEID_NUMERIC(ns[0], 0),
-(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES],NULL, NULL);
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 884LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "InstrumentRange");
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 2370LU),
+UA_NODEID_NUMERIC(ns[0], 2368LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
+UA_QUALIFIEDNAME(ns[0], "InstrumentRange"),
+UA_NODEID_NUMERIC(ns[0], 68LU),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_69_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_67_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2373)
+UA_NODEID_NUMERIC(ns[0], 2370LU)
);
}
-/* FalseState - ns=0;i=2374 */
+/* EURange - ns=0;i=2369 */
-static UA_StatusCode function_namespace0_generated_70_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_68_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_VariableAttributes attr = UA_VariableAttributes_default;
attr.minimumSamplingInterval = 0.000000;
-attr.userAccessLevel = 1;
-attr.accessLevel = 1;
+attr.userAccessLevel = 3;
+attr.accessLevel = 3;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 21);
-attr.displayName = UA_LOCALIZEDTEXT("", "FalseState");
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 884LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "EURange");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 2374),
-UA_NODEID_NUMERIC(ns[0], 2373),
-UA_NODEID_NUMERIC(ns[0], 46),
-UA_QUALIFIEDNAME(ns[0], "FalseState"),
-UA_NODEID_NUMERIC(ns[0], 68),
+UA_NODEID_NUMERIC(ns[0], 2369LU),
+UA_NODEID_NUMERIC(ns[0], 2368LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
+UA_QUALIFIEDNAME(ns[0], "EURange"),
+UA_NODEID_NUMERIC(ns[0], 68LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_70_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_68_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2374)
+UA_NODEID_NUMERIC(ns[0], 2369LU)
);
}
-/* TrueState - ns=0;i=2375 */
+/* ValuePrecision - ns=0;i=2367 */
-static UA_StatusCode function_namespace0_generated_71_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_69_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_VariableAttributes attr = UA_VariableAttributes_default;
attr.minimumSamplingInterval = 0.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 21);
-attr.displayName = UA_LOCALIZEDTEXT("", "TrueState");
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 11LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "ValuePrecision");
+#ifdef UA_ENABLE_NODESET_COMPILER_DESCRIPTIONS
+attr.description = UA_LOCALIZEDTEXT("", "The maximum precision that the server can maintain for the item based on restrictions in the target environment.");
+#endif
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 2375),
-UA_NODEID_NUMERIC(ns[0], 2373),
-UA_NODEID_NUMERIC(ns[0], 46),
-UA_QUALIFIEDNAME(ns[0], "TrueState"),
-UA_NODEID_NUMERIC(ns[0], 68),
+UA_NODEID_NUMERIC(ns[0], 2367LU),
+UA_NODEID_NUMERIC(ns[0], 2365LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
+UA_QUALIFIEDNAME(ns[0], "ValuePrecision"),
+UA_NODEID_NUMERIC(ns[0], 68LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_71_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_69_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2375)
+UA_NODEID_NUMERIC(ns[0], 2367LU)
);
}
/* Definition - ns=0;i=2366 */
-static UA_StatusCode function_namespace0_generated_72_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_70_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_VariableAttributes attr = UA_VariableAttributes_default;
attr.minimumSamplingInterval = 0.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 12);
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 12LU);
attr.displayName = UA_LOCALIZEDTEXT("", "Definition");
#ifdef UA_ENABLE_NODESET_COMPILER_DESCRIPTIONS
attr.description = UA_LOCALIZEDTEXT("", "A vendor-specific, human readable string that specifies how the value of this DataItem is calculated.");
#endif
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 2366),
-UA_NODEID_NUMERIC(ns[0], 2365),
-UA_NODEID_NUMERIC(ns[0], 46),
+UA_NODEID_NUMERIC(ns[0], 2366LU),
+UA_NODEID_NUMERIC(ns[0], 2365LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
UA_QUALIFIEDNAME(ns[0], "Definition"),
-UA_NODEID_NUMERIC(ns[0], 68),
+UA_NODEID_NUMERIC(ns[0], 68LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_72_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_70_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2366)
+UA_NODEID_NUMERIC(ns[0], 2366LU)
);
}
/* HistoryServerCapabilitiesType - ns=0;i=2330 */
-static UA_StatusCode function_namespace0_generated_73_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_71_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default;
attr.displayName = UA_LOCALIZEDTEXT("", "HistoryServerCapabilitiesType");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECTTYPE,
-UA_NODEID_NUMERIC(ns[0], 2330),
-UA_NODEID_NUMERIC(ns[0], 58),
-UA_NODEID_NUMERIC(ns[0], 45),
+UA_NODEID_NUMERIC(ns[0], 2330LU),
+UA_NODEID_NUMERIC(ns[0], 58LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
UA_QUALIFIEDNAME(ns[0], "HistoryServerCapabilitiesType"),
UA_NODEID_NULL,
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_73_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_71_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2330)
+UA_NODEID_NUMERIC(ns[0], 2330LU)
);
}
/* EventQueueOverflowEventType - ns=0;i=3035 */
-static UA_StatusCode function_namespace0_generated_74_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_72_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default;
attr.isAbstract = true;
attr.displayName = UA_LOCALIZEDTEXT("", "EventQueueOverflowEventType");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECTTYPE,
-UA_NODEID_NUMERIC(ns[0], 3035),
-UA_NODEID_NUMERIC(ns[0], 2041),
-UA_NODEID_NUMERIC(ns[0], 45),
+UA_NODEID_NUMERIC(ns[0], 3035LU),
+UA_NODEID_NUMERIC(ns[0], 2041LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
UA_QUALIFIEDNAME(ns[0], "EventQueueOverflowEventType"),
UA_NODEID_NULL,
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_74_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_72_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 3035)
+UA_NODEID_NUMERIC(ns[0], 3035LU)
);
}
/* Severity - ns=0;i=2051 */
-static UA_StatusCode function_namespace0_generated_75_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_73_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_VariableAttributes attr = UA_VariableAttributes_default;
attr.minimumSamplingInterval = 0.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 5);
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 5LU);
attr.displayName = UA_LOCALIZEDTEXT("", "Severity");
#ifdef UA_ENABLE_NODESET_COMPILER_DESCRIPTIONS
attr.description = UA_LOCALIZEDTEXT("", "Indicates how urgent an event is.");
#endif
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 2051),
-UA_NODEID_NUMERIC(ns[0], 2041),
-UA_NODEID_NUMERIC(ns[0], 46),
+UA_NODEID_NUMERIC(ns[0], 2051LU),
+UA_NODEID_NUMERIC(ns[0], 2041LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
UA_QUALIFIEDNAME(ns[0], "Severity"),
-UA_NODEID_NUMERIC(ns[0], 68),
+UA_NODEID_NUMERIC(ns[0], 68LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_75_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_73_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2051)
+UA_NODEID_NUMERIC(ns[0], 2051LU)
);
}
/* Message - ns=0;i=2050 */
-static UA_StatusCode function_namespace0_generated_76_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_74_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_VariableAttributes attr = UA_VariableAttributes_default;
attr.minimumSamplingInterval = 0.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 21);
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 21LU);
attr.displayName = UA_LOCALIZEDTEXT("", "Message");
#ifdef UA_ENABLE_NODESET_COMPILER_DESCRIPTIONS
attr.description = UA_LOCALIZEDTEXT("", "A localized description of the event.");
#endif
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 2050),
-UA_NODEID_NUMERIC(ns[0], 2041),
-UA_NODEID_NUMERIC(ns[0], 46),
+UA_NODEID_NUMERIC(ns[0], 2050LU),
+UA_NODEID_NUMERIC(ns[0], 2041LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
UA_QUALIFIEDNAME(ns[0], "Message"),
-UA_NODEID_NUMERIC(ns[0], 68),
+UA_NODEID_NUMERIC(ns[0], 68LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_76_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_74_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2050)
+UA_NODEID_NUMERIC(ns[0], 2050LU)
);
}
/* LocalTime - ns=0;i=3190 */
-static UA_StatusCode function_namespace0_generated_77_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_75_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_VariableAttributes attr = UA_VariableAttributes_default;
attr.minimumSamplingInterval = 0.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 8912);
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 8912LU);
attr.displayName = UA_LOCALIZEDTEXT("", "LocalTime");
#ifdef UA_ENABLE_NODESET_COMPILER_DESCRIPTIONS
attr.description = UA_LOCALIZEDTEXT("", "Information about the local time where the event originated.");
#endif
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 3190),
-UA_NODEID_NUMERIC(ns[0], 2041),
-UA_NODEID_NUMERIC(ns[0], 46),
+UA_NODEID_NUMERIC(ns[0], 3190LU),
+UA_NODEID_NUMERIC(ns[0], 2041LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
UA_QUALIFIEDNAME(ns[0], "LocalTime"),
-UA_NODEID_NUMERIC(ns[0], 68),
+UA_NODEID_NUMERIC(ns[0], 68LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_77_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_75_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 3190)
+UA_NODEID_NUMERIC(ns[0], 3190LU)
);
}
/* ReceiveTime - ns=0;i=2047 */
-static UA_StatusCode function_namespace0_generated_78_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_76_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_VariableAttributes attr = UA_VariableAttributes_default;
attr.minimumSamplingInterval = 0.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 294);
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 294LU);
attr.displayName = UA_LOCALIZEDTEXT("", "ReceiveTime");
#ifdef UA_ENABLE_NODESET_COMPILER_DESCRIPTIONS
attr.description = UA_LOCALIZEDTEXT("", "When the server received the event from the underlying system.");
#endif
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 2047),
-UA_NODEID_NUMERIC(ns[0], 2041),
-UA_NODEID_NUMERIC(ns[0], 46),
+UA_NODEID_NUMERIC(ns[0], 2047LU),
+UA_NODEID_NUMERIC(ns[0], 2041LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
UA_QUALIFIEDNAME(ns[0], "ReceiveTime"),
-UA_NODEID_NUMERIC(ns[0], 68),
+UA_NODEID_NUMERIC(ns[0], 68LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_78_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_76_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2047)
+UA_NODEID_NUMERIC(ns[0], 2047LU)
);
}
/* Time - ns=0;i=2046 */
-static UA_StatusCode function_namespace0_generated_79_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_77_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_VariableAttributes attr = UA_VariableAttributes_default;
attr.minimumSamplingInterval = 0.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 294);
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 294LU);
attr.displayName = UA_LOCALIZEDTEXT("", "Time");
#ifdef UA_ENABLE_NODESET_COMPILER_DESCRIPTIONS
attr.description = UA_LOCALIZEDTEXT("", "When the event occurred.");
#endif
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 2046),
-UA_NODEID_NUMERIC(ns[0], 2041),
-UA_NODEID_NUMERIC(ns[0], 46),
+UA_NODEID_NUMERIC(ns[0], 2046LU),
+UA_NODEID_NUMERIC(ns[0], 2041LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
UA_QUALIFIEDNAME(ns[0], "Time"),
-UA_NODEID_NUMERIC(ns[0], 68),
+UA_NODEID_NUMERIC(ns[0], 68LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_79_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_77_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2046)
+UA_NODEID_NUMERIC(ns[0], 2046LU)
);
}
/* SourceName - ns=0;i=2045 */
-static UA_StatusCode function_namespace0_generated_80_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_78_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_VariableAttributes attr = UA_VariableAttributes_default;
attr.minimumSamplingInterval = 0.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 12);
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 12LU);
attr.displayName = UA_LOCALIZEDTEXT("", "SourceName");
#ifdef UA_ENABLE_NODESET_COMPILER_DESCRIPTIONS
attr.description = UA_LOCALIZEDTEXT("", "A description of the source of the event.");
#endif
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 2045),
-UA_NODEID_NUMERIC(ns[0], 2041),
-UA_NODEID_NUMERIC(ns[0], 46),
+UA_NODEID_NUMERIC(ns[0], 2045LU),
+UA_NODEID_NUMERIC(ns[0], 2041LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
UA_QUALIFIEDNAME(ns[0], "SourceName"),
-UA_NODEID_NUMERIC(ns[0], 68),
+UA_NODEID_NUMERIC(ns[0], 68LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_80_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_78_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2045)
+UA_NODEID_NUMERIC(ns[0], 2045LU)
);
}
/* SourceNode - ns=0;i=2044 */
-static UA_StatusCode function_namespace0_generated_81_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_79_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_VariableAttributes attr = UA_VariableAttributes_default;
attr.minimumSamplingInterval = 0.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 17);
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 17LU);
attr.displayName = UA_LOCALIZEDTEXT("", "SourceNode");
#ifdef UA_ENABLE_NODESET_COMPILER_DESCRIPTIONS
attr.description = UA_LOCALIZEDTEXT("", "The source of the event.");
#endif
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 2044),
-UA_NODEID_NUMERIC(ns[0], 2041),
-UA_NODEID_NUMERIC(ns[0], 46),
+UA_NODEID_NUMERIC(ns[0], 2044LU),
+UA_NODEID_NUMERIC(ns[0], 2041LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
UA_QUALIFIEDNAME(ns[0], "SourceNode"),
-UA_NODEID_NUMERIC(ns[0], 68),
+UA_NODEID_NUMERIC(ns[0], 68LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_81_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_79_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2044)
+UA_NODEID_NUMERIC(ns[0], 2044LU)
);
}
/* EventType - ns=0;i=2043 */
-static UA_StatusCode function_namespace0_generated_82_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_80_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_VariableAttributes attr = UA_VariableAttributes_default;
attr.minimumSamplingInterval = 0.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 17);
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 17LU);
attr.displayName = UA_LOCALIZEDTEXT("", "EventType");
#ifdef UA_ENABLE_NODESET_COMPILER_DESCRIPTIONS
attr.description = UA_LOCALIZEDTEXT("", "The identifier for the event type.");
#endif
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 2043),
-UA_NODEID_NUMERIC(ns[0], 2041),
-UA_NODEID_NUMERIC(ns[0], 46),
+UA_NODEID_NUMERIC(ns[0], 2043LU),
+UA_NODEID_NUMERIC(ns[0], 2041LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
UA_QUALIFIEDNAME(ns[0], "EventType"),
-UA_NODEID_NUMERIC(ns[0], 68),
+UA_NODEID_NUMERIC(ns[0], 68LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_82_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_80_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2043)
+UA_NODEID_NUMERIC(ns[0], 2043LU)
);
}
/* EventId - ns=0;i=2042 */
-static UA_StatusCode function_namespace0_generated_83_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_81_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_VariableAttributes attr = UA_VariableAttributes_default;
attr.minimumSamplingInterval = 0.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 15);
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 15LU);
attr.displayName = UA_LOCALIZEDTEXT("", "EventId");
#ifdef UA_ENABLE_NODESET_COMPILER_DESCRIPTIONS
attr.description = UA_LOCALIZEDTEXT("", "A globally unique identifier for the event.");
#endif
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 2042),
-UA_NODEID_NUMERIC(ns[0], 2041),
-UA_NODEID_NUMERIC(ns[0], 46),
+UA_NODEID_NUMERIC(ns[0], 2042LU),
+UA_NODEID_NUMERIC(ns[0], 2041LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
UA_QUALIFIEDNAME(ns[0], "EventId"),
-UA_NODEID_NUMERIC(ns[0], 68),
+UA_NODEID_NUMERIC(ns[0], 68LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_83_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_81_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2042)
+UA_NODEID_NUMERIC(ns[0], 2042LU)
);
}
/* InterfaceTypes - ns=0;i=17708 */
-static UA_StatusCode function_namespace0_generated_84_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_82_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_ObjectAttributes attr = UA_ObjectAttributes_default;
attr.displayName = UA_LOCALIZEDTEXT("", "InterfaceTypes");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECT,
-UA_NODEID_NUMERIC(ns[0], 17708),
-UA_NODEID_NUMERIC(ns[0], 86),
-UA_NODEID_NUMERIC(ns[0], 35),
+UA_NODEID_NUMERIC(ns[0], 17708LU),
+UA_NODEID_NUMERIC(ns[0], 86LU),
+UA_NODEID_NUMERIC(ns[0], 35LU),
UA_QUALIFIEDNAME(ns[0], "InterfaceTypes"),
-UA_NODEID_NUMERIC(ns[0], 61),
+UA_NODEID_NUMERIC(ns[0], 61LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_84_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_82_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 17708)
+UA_NODEID_NUMERIC(ns[0], 17708LU)
);
}
/* BaseInterfaceType - ns=0;i=17602 */
-static UA_StatusCode function_namespace0_generated_85_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_83_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default;
attr.isAbstract = true;
attr.displayName = UA_LOCALIZEDTEXT("", "BaseInterfaceType");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECTTYPE,
-UA_NODEID_NUMERIC(ns[0], 17602),
-UA_NODEID_NUMERIC(ns[0], 58),
-UA_NODEID_NUMERIC(ns[0], 45),
+UA_NODEID_NUMERIC(ns[0], 17602LU),
+UA_NODEID_NUMERIC(ns[0], 58LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
UA_QUALIFIEDNAME(ns[0], "BaseInterfaceType"),
UA_NODEID_NULL,
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL);
-retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 17602), UA_NODEID_NUMERIC(ns[0], 35), UA_EXPANDEDNODEID_NUMERIC(ns[0], 17708), false);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 17602LU), UA_NODEID_NUMERIC(ns[0], 35LU), UA_EXPANDEDNODEID_NUMERIC(ns[0], 17708LU), false);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_85_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_83_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 17602)
+UA_NODEID_NUMERIC(ns[0], 17602LU)
);
}
-/* ServerDiagnosticsSummaryType - ns=0;i=2150 */
+/* BuildInfoType - ns=0;i=3051 */
-static UA_StatusCode function_namespace0_generated_86_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_84_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_VariableTypeAttributes attr = UA_VariableTypeAttributes_default;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 859);
-attr.displayName = UA_LOCALIZEDTEXT("", "ServerDiagnosticsSummaryType");
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 338LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "BuildInfoType");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLETYPE,
-UA_NODEID_NUMERIC(ns[0], 2150),
-UA_NODEID_NUMERIC(ns[0], 63),
-UA_NODEID_NUMERIC(ns[0], 45),
-UA_QUALIFIEDNAME(ns[0], "ServerDiagnosticsSummaryType"),
-UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 3051LU),
+UA_NODEID_NUMERIC(ns[0], 63LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
+UA_QUALIFIEDNAME(ns[0], "BuildInfoType"),
+UA_NODEID_NUMERIC(ns[0], 0LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES],NULL, NULL);
return retVal;
}
+static UA_StatusCode function_namespace0_generated_84_finish(UA_Server *server, UA_UInt16* ns) {
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 3051LU)
+);
+}
+
+/* ServerStatusType - ns=0;i=2138 */
+
+static UA_StatusCode function_namespace0_generated_85_begin(UA_Server *server, UA_UInt16* ns) {
+UA_StatusCode retVal = UA_STATUSCODE_GOOD;
+UA_VariableTypeAttributes attr = UA_VariableTypeAttributes_default;
+/* Value rank inherited */
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 862LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "ServerStatusType");
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLETYPE,
+UA_NODEID_NUMERIC(ns[0], 2138LU),
+UA_NODEID_NUMERIC(ns[0], 63LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
+UA_QUALIFIEDNAME(ns[0], "ServerStatusType"),
+UA_NODEID_NUMERIC(ns[0], 0LU),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES],NULL, NULL);
+return retVal;
+}
+
+static UA_StatusCode function_namespace0_generated_85_finish(UA_Server *server, UA_UInt16* ns) {
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 2138LU)
+);
+}
+
+/* OperationLimitsType - ns=0;i=11564 */
+
+static UA_StatusCode function_namespace0_generated_86_begin(UA_Server *server, UA_UInt16* ns) {
+UA_StatusCode retVal = UA_STATUSCODE_GOOD;
+UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default;
+attr.displayName = UA_LOCALIZEDTEXT("", "OperationLimitsType");
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECTTYPE,
+UA_NODEID_NUMERIC(ns[0], 11564LU),
+UA_NODEID_NUMERIC(ns[0], 61LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
+UA_QUALIFIEDNAME(ns[0], "OperationLimitsType"),
+ UA_NODEID_NULL,
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL);
+return retVal;
+}
+
static UA_StatusCode function_namespace0_generated_86_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2150)
+UA_NODEID_NUMERIC(ns[0], 11564LU)
);
}
-/* PublishingIntervalCount - ns=0;i=2159 */
+/* MaxMonitoredItemsPerCall - ns=0;i=11574 */
static UA_StatusCode function_namespace0_generated_87_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
@@ -48438,26 +54146,26 @@ attr.minimumSamplingInterval = 0.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 7);
-attr.displayName = UA_LOCALIZEDTEXT("", "PublishingIntervalCount");
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 7LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "MaxMonitoredItemsPerCall");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 2159),
-UA_NODEID_NUMERIC(ns[0], 2150),
-UA_NODEID_NUMERIC(ns[0], 47),
-UA_QUALIFIEDNAME(ns[0], "PublishingIntervalCount"),
-UA_NODEID_NUMERIC(ns[0], 63),
+UA_NODEID_NUMERIC(ns[0], 11574LU),
+UA_NODEID_NUMERIC(ns[0], 11564LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
+UA_QUALIFIEDNAME(ns[0], "MaxMonitoredItemsPerCall"),
+UA_NODEID_NUMERIC(ns[0], 68LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
static UA_StatusCode function_namespace0_generated_87_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2159)
+UA_NODEID_NUMERIC(ns[0], 11574LU)
);
}
-/* SecurityRejectedSessionCount - ns=0;i=2154 */
+/* MaxNodesPerNodeManagement - ns=0;i=11573 */
static UA_StatusCode function_namespace0_generated_88_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
@@ -48466,26 +54174,26 @@ attr.minimumSamplingInterval = 0.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 7);
-attr.displayName = UA_LOCALIZEDTEXT("", "SecurityRejectedSessionCount");
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 7LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "MaxNodesPerNodeManagement");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 2154),
-UA_NODEID_NUMERIC(ns[0], 2150),
-UA_NODEID_NUMERIC(ns[0], 47),
-UA_QUALIFIEDNAME(ns[0], "SecurityRejectedSessionCount"),
-UA_NODEID_NUMERIC(ns[0], 63),
+UA_NODEID_NUMERIC(ns[0], 11573LU),
+UA_NODEID_NUMERIC(ns[0], 11564LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
+UA_QUALIFIEDNAME(ns[0], "MaxNodesPerNodeManagement"),
+UA_NODEID_NUMERIC(ns[0], 68LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
static UA_StatusCode function_namespace0_generated_88_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2154)
+UA_NODEID_NUMERIC(ns[0], 11573LU)
);
}
-/* SessionAbortCount - ns=0;i=2157 */
+/* MaxNodesPerTranslateBrowsePathsToNodeIds - ns=0;i=11572 */
static UA_StatusCode function_namespace0_generated_89_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
@@ -48494,26 +54202,26 @@ attr.minimumSamplingInterval = 0.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 7);
-attr.displayName = UA_LOCALIZEDTEXT("", "SessionAbortCount");
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 7LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "MaxNodesPerTranslateBrowsePathsToNodeIds");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 2157),
-UA_NODEID_NUMERIC(ns[0], 2150),
-UA_NODEID_NUMERIC(ns[0], 47),
-UA_QUALIFIEDNAME(ns[0], "SessionAbortCount"),
-UA_NODEID_NUMERIC(ns[0], 63),
+UA_NODEID_NUMERIC(ns[0], 11572LU),
+UA_NODEID_NUMERIC(ns[0], 11564LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
+UA_QUALIFIEDNAME(ns[0], "MaxNodesPerTranslateBrowsePathsToNodeIds"),
+UA_NODEID_NUMERIC(ns[0], 68LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
static UA_StatusCode function_namespace0_generated_89_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2157)
+UA_NODEID_NUMERIC(ns[0], 11572LU)
);
}
-/* ServerViewCount - ns=0;i=2151 */
+/* MaxNodesPerRegisterNodes - ns=0;i=11571 */
static UA_StatusCode function_namespace0_generated_90_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
@@ -48522,26 +54230,26 @@ attr.minimumSamplingInterval = 0.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 7);
-attr.displayName = UA_LOCALIZEDTEXT("", "ServerViewCount");
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 7LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "MaxNodesPerRegisterNodes");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 2151),
-UA_NODEID_NUMERIC(ns[0], 2150),
-UA_NODEID_NUMERIC(ns[0], 47),
-UA_QUALIFIEDNAME(ns[0], "ServerViewCount"),
-UA_NODEID_NUMERIC(ns[0], 63),
+UA_NODEID_NUMERIC(ns[0], 11571LU),
+UA_NODEID_NUMERIC(ns[0], 11564LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
+UA_QUALIFIEDNAME(ns[0], "MaxNodesPerRegisterNodes"),
+UA_NODEID_NUMERIC(ns[0], 68LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
static UA_StatusCode function_namespace0_generated_90_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2151)
+UA_NODEID_NUMERIC(ns[0], 11571LU)
);
}
-/* RejectedRequestsCount - ns=0;i=2163 */
+/* MaxNodesPerBrowse - ns=0;i=11570 */
static UA_StatusCode function_namespace0_generated_91_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
@@ -48550,26 +54258,26 @@ attr.minimumSamplingInterval = 0.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 7);
-attr.displayName = UA_LOCALIZEDTEXT("", "RejectedRequestsCount");
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 7LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "MaxNodesPerBrowse");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 2163),
-UA_NODEID_NUMERIC(ns[0], 2150),
-UA_NODEID_NUMERIC(ns[0], 47),
-UA_QUALIFIEDNAME(ns[0], "RejectedRequestsCount"),
-UA_NODEID_NUMERIC(ns[0], 63),
+UA_NODEID_NUMERIC(ns[0], 11570LU),
+UA_NODEID_NUMERIC(ns[0], 11564LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
+UA_QUALIFIEDNAME(ns[0], "MaxNodesPerBrowse"),
+UA_NODEID_NUMERIC(ns[0], 68LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
static UA_StatusCode function_namespace0_generated_91_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2163)
+UA_NODEID_NUMERIC(ns[0], 11570LU)
);
}
-/* SessionTimeoutCount - ns=0;i=2156 */
+/* MaxNodesPerMethodCall - ns=0;i=11569 */
static UA_StatusCode function_namespace0_generated_92_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
@@ -48578,26 +54286,26 @@ attr.minimumSamplingInterval = 0.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 7);
-attr.displayName = UA_LOCALIZEDTEXT("", "SessionTimeoutCount");
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 7LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "MaxNodesPerMethodCall");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 2156),
-UA_NODEID_NUMERIC(ns[0], 2150),
-UA_NODEID_NUMERIC(ns[0], 47),
-UA_QUALIFIEDNAME(ns[0], "SessionTimeoutCount"),
-UA_NODEID_NUMERIC(ns[0], 63),
+UA_NODEID_NUMERIC(ns[0], 11569LU),
+UA_NODEID_NUMERIC(ns[0], 11564LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
+UA_QUALIFIEDNAME(ns[0], "MaxNodesPerMethodCall"),
+UA_NODEID_NUMERIC(ns[0], 68LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
static UA_StatusCode function_namespace0_generated_92_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2156)
+UA_NODEID_NUMERIC(ns[0], 11569LU)
);
}
-/* CurrentSessionCount - ns=0;i=2152 */
+/* MaxNodesPerWrite - ns=0;i=11567 */
static UA_StatusCode function_namespace0_generated_93_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
@@ -48606,26 +54314,26 @@ attr.minimumSamplingInterval = 0.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 7);
-attr.displayName = UA_LOCALIZEDTEXT("", "CurrentSessionCount");
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 7LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "MaxNodesPerWrite");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 2152),
-UA_NODEID_NUMERIC(ns[0], 2150),
-UA_NODEID_NUMERIC(ns[0], 47),
-UA_QUALIFIEDNAME(ns[0], "CurrentSessionCount"),
-UA_NODEID_NUMERIC(ns[0], 63),
+UA_NODEID_NUMERIC(ns[0], 11567LU),
+UA_NODEID_NUMERIC(ns[0], 11564LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
+UA_QUALIFIEDNAME(ns[0], "MaxNodesPerWrite"),
+UA_NODEID_NUMERIC(ns[0], 68LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
static UA_StatusCode function_namespace0_generated_93_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2152)
+UA_NODEID_NUMERIC(ns[0], 11567LU)
);
}
-/* CumulatedSubscriptionCount - ns=0;i=2161 */
+/* MaxNodesPerRead - ns=0;i=11565 */
static UA_StatusCode function_namespace0_generated_94_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
@@ -48634,54 +54342,48 @@ attr.minimumSamplingInterval = 0.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 7);
-attr.displayName = UA_LOCALIZEDTEXT("", "CumulatedSubscriptionCount");
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 7LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "MaxNodesPerRead");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 2161),
-UA_NODEID_NUMERIC(ns[0], 2150),
-UA_NODEID_NUMERIC(ns[0], 47),
-UA_QUALIFIEDNAME(ns[0], "CumulatedSubscriptionCount"),
-UA_NODEID_NUMERIC(ns[0], 63),
+UA_NODEID_NUMERIC(ns[0], 11565LU),
+UA_NODEID_NUMERIC(ns[0], 11564LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
+UA_QUALIFIEDNAME(ns[0], "MaxNodesPerRead"),
+UA_NODEID_NUMERIC(ns[0], 68LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
static UA_StatusCode function_namespace0_generated_94_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2161)
+UA_NODEID_NUMERIC(ns[0], 11565LU)
);
}
-/* SecurityRejectedRequestsCount - ns=0;i=2162 */
+/* ServerRedundancyType - ns=0;i=2034 */
static UA_StatusCode function_namespace0_generated_95_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
-UA_VariableAttributes attr = UA_VariableAttributes_default;
-attr.minimumSamplingInterval = 0.000000;
-attr.userAccessLevel = 1;
-attr.accessLevel = 1;
-/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 7);
-attr.displayName = UA_LOCALIZEDTEXT("", "SecurityRejectedRequestsCount");
-retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 2162),
-UA_NODEID_NUMERIC(ns[0], 2150),
-UA_NODEID_NUMERIC(ns[0], 47),
-UA_QUALIFIEDNAME(ns[0], "SecurityRejectedRequestsCount"),
-UA_NODEID_NUMERIC(ns[0], 63),
-(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default;
+attr.displayName = UA_LOCALIZEDTEXT("", "ServerRedundancyType");
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECTTYPE,
+UA_NODEID_NUMERIC(ns[0], 2034LU),
+UA_NODEID_NUMERIC(ns[0], 58LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
+UA_QUALIFIEDNAME(ns[0], "ServerRedundancyType"),
+ UA_NODEID_NULL,
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL);
return retVal;
}
static UA_StatusCode function_namespace0_generated_95_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2162)
+UA_NODEID_NUMERIC(ns[0], 2034LU)
);
}
-/* CumulatedSessionCount - ns=0;i=2153 */
+/* RedundancySupport - ns=0;i=2035 */
static UA_StatusCode function_namespace0_generated_96_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
@@ -48690,142 +54392,124 @@ attr.minimumSamplingInterval = 0.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 7);
-attr.displayName = UA_LOCALIZEDTEXT("", "CumulatedSessionCount");
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 851LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "RedundancySupport");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 2153),
-UA_NODEID_NUMERIC(ns[0], 2150),
-UA_NODEID_NUMERIC(ns[0], 47),
-UA_QUALIFIEDNAME(ns[0], "CumulatedSessionCount"),
-UA_NODEID_NUMERIC(ns[0], 63),
+UA_NODEID_NUMERIC(ns[0], 2035LU),
+UA_NODEID_NUMERIC(ns[0], 2034LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
+UA_QUALIFIEDNAME(ns[0], "RedundancySupport"),
+UA_NODEID_NUMERIC(ns[0], 68LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
static UA_StatusCode function_namespace0_generated_96_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2153)
+UA_NODEID_NUMERIC(ns[0], 2035LU)
);
}
-/* CurrentSubscriptionCount - ns=0;i=2160 */
+/* VendorServerInfoType - ns=0;i=2033 */
static UA_StatusCode function_namespace0_generated_97_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
-UA_VariableAttributes attr = UA_VariableAttributes_default;
-attr.minimumSamplingInterval = 0.000000;
-attr.userAccessLevel = 1;
-attr.accessLevel = 1;
-/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 7);
-attr.displayName = UA_LOCALIZEDTEXT("", "CurrentSubscriptionCount");
-retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 2160),
-UA_NODEID_NUMERIC(ns[0], 2150),
-UA_NODEID_NUMERIC(ns[0], 47),
-UA_QUALIFIEDNAME(ns[0], "CurrentSubscriptionCount"),
-UA_NODEID_NUMERIC(ns[0], 63),
-(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default;
+attr.displayName = UA_LOCALIZEDTEXT("", "VendorServerInfoType");
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECTTYPE,
+UA_NODEID_NUMERIC(ns[0], 2033LU),
+UA_NODEID_NUMERIC(ns[0], 58LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
+UA_QUALIFIEDNAME(ns[0], "VendorServerInfoType"),
+ UA_NODEID_NULL,
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL);
return retVal;
}
static UA_StatusCode function_namespace0_generated_97_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2160)
+UA_NODEID_NUMERIC(ns[0], 2033LU)
);
}
-/* RejectedSessionCount - ns=0;i=2155 */
+/* ServerDiagnosticsType - ns=0;i=2020 */
static UA_StatusCode function_namespace0_generated_98_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
-UA_VariableAttributes attr = UA_VariableAttributes_default;
-attr.minimumSamplingInterval = 0.000000;
-attr.userAccessLevel = 1;
-attr.accessLevel = 1;
-/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 7);
-attr.displayName = UA_LOCALIZEDTEXT("", "RejectedSessionCount");
-retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 2155),
-UA_NODEID_NUMERIC(ns[0], 2150),
-UA_NODEID_NUMERIC(ns[0], 47),
-UA_QUALIFIEDNAME(ns[0], "RejectedSessionCount"),
-UA_NODEID_NUMERIC(ns[0], 63),
-(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default;
+attr.displayName = UA_LOCALIZEDTEXT("", "ServerDiagnosticsType");
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECTTYPE,
+UA_NODEID_NUMERIC(ns[0], 2020LU),
+UA_NODEID_NUMERIC(ns[0], 58LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
+UA_QUALIFIEDNAME(ns[0], "ServerDiagnosticsType"),
+ UA_NODEID_NULL,
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL);
return retVal;
}
static UA_StatusCode function_namespace0_generated_98_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2155)
+UA_NODEID_NUMERIC(ns[0], 2020LU)
);
}
-/* BuildInfoType - ns=0;i=3051 */
+/* ServerCapabilitiesType - ns=0;i=2013 */
static UA_StatusCode function_namespace0_generated_99_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
-UA_VariableTypeAttributes attr = UA_VariableTypeAttributes_default;
-/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 338);
-attr.displayName = UA_LOCALIZEDTEXT("", "BuildInfoType");
-retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLETYPE,
-UA_NODEID_NUMERIC(ns[0], 3051),
-UA_NODEID_NUMERIC(ns[0], 63),
-UA_NODEID_NUMERIC(ns[0], 45),
-UA_QUALIFIEDNAME(ns[0], "BuildInfoType"),
-UA_NODEID_NUMERIC(ns[0], 0),
-(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES],NULL, NULL);
+UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default;
+attr.displayName = UA_LOCALIZEDTEXT("", "ServerCapabilitiesType");
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECTTYPE,
+UA_NODEID_NUMERIC(ns[0], 2013LU),
+UA_NODEID_NUMERIC(ns[0], 58LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
+UA_QUALIFIEDNAME(ns[0], "ServerCapabilitiesType"),
+ UA_NODEID_NULL,
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL);
return retVal;
}
static UA_StatusCode function_namespace0_generated_99_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 3051)
+UA_NODEID_NUMERIC(ns[0], 2013LU)
);
}
-/* ServerStatusType - ns=0;i=2138 */
+/* OperationLimits - ns=0;i=11551 */
static UA_StatusCode function_namespace0_generated_100_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
-UA_VariableTypeAttributes attr = UA_VariableTypeAttributes_default;
-/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 862);
-attr.displayName = UA_LOCALIZEDTEXT("", "ServerStatusType");
-retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLETYPE,
-UA_NODEID_NUMERIC(ns[0], 2138),
-UA_NODEID_NUMERIC(ns[0], 63),
-UA_NODEID_NUMERIC(ns[0], 45),
-UA_QUALIFIEDNAME(ns[0], "ServerStatusType"),
-UA_NODEID_NUMERIC(ns[0], 0),
-(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES],NULL, NULL);
+UA_ObjectAttributes attr = UA_ObjectAttributes_default;
+attr.displayName = UA_LOCALIZEDTEXT("", "OperationLimits");
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECT,
+UA_NODEID_NUMERIC(ns[0], 11551LU),
+UA_NODEID_NUMERIC(ns[0], 2013LU),
+UA_NODEID_NUMERIC(ns[0], 47LU),
+UA_QUALIFIEDNAME(ns[0], "OperationLimits"),
+UA_NODEID_NUMERIC(ns[0], 11564LU),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
return retVal;
}
static UA_StatusCode function_namespace0_generated_100_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2138)
+UA_NODEID_NUMERIC(ns[0], 11551LU)
);
}
-/* OperationLimitsType - ns=0;i=11564 */
+/* ServerType - ns=0;i=2004 */
static UA_StatusCode function_namespace0_generated_101_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default;
-attr.displayName = UA_LOCALIZEDTEXT("", "OperationLimitsType");
+attr.displayName = UA_LOCALIZEDTEXT("", "ServerType");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECTTYPE,
-UA_NODEID_NUMERIC(ns[0], 11564),
-UA_NODEID_NUMERIC(ns[0], 61),
-UA_NODEID_NUMERIC(ns[0], 45),
-UA_QUALIFIEDNAME(ns[0], "OperationLimitsType"),
+UA_NODEID_NUMERIC(ns[0], 2004LU),
+UA_NODEID_NUMERIC(ns[0], 58LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
+UA_QUALIFIEDNAME(ns[0], "ServerType"),
UA_NODEID_NULL,
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL);
return retVal;
@@ -48833,95 +54517,84 @@ return retVal;
static UA_StatusCode function_namespace0_generated_101_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 11564)
+UA_NODEID_NUMERIC(ns[0], 2004LU)
);
}
-/* MaxNodesPerMethodCall - ns=0;i=11569 */
+/* Server - ns=0;i=2253 */
static UA_StatusCode function_namespace0_generated_102_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
-UA_VariableAttributes attr = UA_VariableAttributes_default;
-attr.minimumSamplingInterval = 0.000000;
-attr.userAccessLevel = 1;
-attr.accessLevel = 1;
-/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 7);
-attr.displayName = UA_LOCALIZEDTEXT("", "MaxNodesPerMethodCall");
-retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 11569),
-UA_NODEID_NUMERIC(ns[0], 11564),
-UA_NODEID_NUMERIC(ns[0], 46),
-UA_QUALIFIEDNAME(ns[0], "MaxNodesPerMethodCall"),
-UA_NODEID_NUMERIC(ns[0], 68),
-(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+UA_ObjectAttributes attr = UA_ObjectAttributes_default;
+attr.eventNotifier = UA_EVENTNOTIFIER_SUBSCRIBE_TO_EVENT;
+attr.displayName = UA_LOCALIZEDTEXT("", "Server");
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECT,
+UA_NODEID_NUMERIC(ns[0], 2253LU),
+UA_NODEID_NUMERIC(ns[0], 85LU),
+UA_NODEID_NUMERIC(ns[0], 35LU),
+UA_QUALIFIEDNAME(ns[0], "Server"),
+UA_NODEID_NUMERIC(ns[0], 2004LU),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
return retVal;
}
static UA_StatusCode function_namespace0_generated_102_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 11569)
+UA_NODEID_NUMERIC(ns[0], 2253LU)
);
}
-/* MaxNodesPerWrite - ns=0;i=11567 */
+/* Auditing - ns=0;i=2994 */
static UA_StatusCode function_namespace0_generated_103_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_VariableAttributes attr = UA_VariableAttributes_default;
-attr.minimumSamplingInterval = 0.000000;
+attr.minimumSamplingInterval = 1000.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 7);
-attr.displayName = UA_LOCALIZEDTEXT("", "MaxNodesPerWrite");
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 1LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "Auditing");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 11567),
-UA_NODEID_NUMERIC(ns[0], 11564),
-UA_NODEID_NUMERIC(ns[0], 46),
-UA_QUALIFIEDNAME(ns[0], "MaxNodesPerWrite"),
-UA_NODEID_NUMERIC(ns[0], 68),
+UA_NODEID_NUMERIC(ns[0], 2994LU),
+UA_NODEID_NUMERIC(ns[0], 2253LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
+UA_QUALIFIEDNAME(ns[0], "Auditing"),
+UA_NODEID_NUMERIC(ns[0], 68LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
static UA_StatusCode function_namespace0_generated_103_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 11567)
+UA_NODEID_NUMERIC(ns[0], 2994LU)
);
}
-/* MaxNodesPerRead - ns=0;i=11565 */
+/* ServerRedundancy - ns=0;i=2296 */
static UA_StatusCode function_namespace0_generated_104_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
-UA_VariableAttributes attr = UA_VariableAttributes_default;
-attr.minimumSamplingInterval = 0.000000;
-attr.userAccessLevel = 1;
-attr.accessLevel = 1;
-/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 7);
-attr.displayName = UA_LOCALIZEDTEXT("", "MaxNodesPerRead");
-retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 11565),
-UA_NODEID_NUMERIC(ns[0], 11564),
-UA_NODEID_NUMERIC(ns[0], 46),
-UA_QUALIFIEDNAME(ns[0], "MaxNodesPerRead"),
-UA_NODEID_NUMERIC(ns[0], 68),
-(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+UA_ObjectAttributes attr = UA_ObjectAttributes_default;
+attr.displayName = UA_LOCALIZEDTEXT("", "ServerRedundancy");
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECT,
+UA_NODEID_NUMERIC(ns[0], 2296LU),
+UA_NODEID_NUMERIC(ns[0], 2253LU),
+UA_NODEID_NUMERIC(ns[0], 47LU),
+UA_QUALIFIEDNAME(ns[0], "ServerRedundancy"),
+UA_NODEID_NUMERIC(ns[0], 2034LU),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
return retVal;
}
static UA_StatusCode function_namespace0_generated_104_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 11565)
+UA_NODEID_NUMERIC(ns[0], 2296LU)
);
}
-/* MaxNodesPerTranslateBrowsePathsToNodeIds - ns=0;i=11572 */
+/* RedundancySupport - ns=0;i=3709 */
static UA_StatusCode function_namespace0_generated_105_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
@@ -48930,462 +54603,475 @@ attr.minimumSamplingInterval = 0.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 7);
-attr.displayName = UA_LOCALIZEDTEXT("", "MaxNodesPerTranslateBrowsePathsToNodeIds");
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 851LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "RedundancySupport");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 11572),
-UA_NODEID_NUMERIC(ns[0], 11564),
-UA_NODEID_NUMERIC(ns[0], 46),
-UA_QUALIFIEDNAME(ns[0], "MaxNodesPerTranslateBrowsePathsToNodeIds"),
-UA_NODEID_NUMERIC(ns[0], 68),
+UA_NODEID_NUMERIC(ns[0], 3709LU),
+UA_NODEID_NUMERIC(ns[0], 2296LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
+UA_QUALIFIEDNAME(ns[0], "RedundancySupport"),
+UA_NODEID_NUMERIC(ns[0], 68LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
static UA_StatusCode function_namespace0_generated_105_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 11572)
+UA_NODEID_NUMERIC(ns[0], 3709LU)
);
}
-/* MaxMonitoredItemsPerCall - ns=0;i=11574 */
+/* VendorServerInfo - ns=0;i=2295 */
static UA_StatusCode function_namespace0_generated_106_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
-UA_VariableAttributes attr = UA_VariableAttributes_default;
-attr.minimumSamplingInterval = 0.000000;
-attr.userAccessLevel = 1;
-attr.accessLevel = 1;
-/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 7);
-attr.displayName = UA_LOCALIZEDTEXT("", "MaxMonitoredItemsPerCall");
-retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 11574),
-UA_NODEID_NUMERIC(ns[0], 11564),
-UA_NODEID_NUMERIC(ns[0], 46),
-UA_QUALIFIEDNAME(ns[0], "MaxMonitoredItemsPerCall"),
-UA_NODEID_NUMERIC(ns[0], 68),
-(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+UA_ObjectAttributes attr = UA_ObjectAttributes_default;
+attr.displayName = UA_LOCALIZEDTEXT("", "VendorServerInfo");
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECT,
+UA_NODEID_NUMERIC(ns[0], 2295LU),
+UA_NODEID_NUMERIC(ns[0], 2253LU),
+UA_NODEID_NUMERIC(ns[0], 47LU),
+UA_QUALIFIEDNAME(ns[0], "VendorServerInfo"),
+UA_NODEID_NUMERIC(ns[0], 2033LU),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
return retVal;
}
static UA_StatusCode function_namespace0_generated_106_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 11574)
+UA_NODEID_NUMERIC(ns[0], 2295LU)
);
}
-/* MaxNodesPerRegisterNodes - ns=0;i=11571 */
+/* ServerDiagnostics - ns=0;i=2274 */
static UA_StatusCode function_namespace0_generated_107_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
-UA_VariableAttributes attr = UA_VariableAttributes_default;
-attr.minimumSamplingInterval = 0.000000;
-attr.userAccessLevel = 1;
-attr.accessLevel = 1;
-/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 7);
-attr.displayName = UA_LOCALIZEDTEXT("", "MaxNodesPerRegisterNodes");
-retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 11571),
-UA_NODEID_NUMERIC(ns[0], 11564),
-UA_NODEID_NUMERIC(ns[0], 46),
-UA_QUALIFIEDNAME(ns[0], "MaxNodesPerRegisterNodes"),
-UA_NODEID_NUMERIC(ns[0], 68),
-(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+UA_ObjectAttributes attr = UA_ObjectAttributes_default;
+attr.displayName = UA_LOCALIZEDTEXT("", "ServerDiagnostics");
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECT,
+UA_NODEID_NUMERIC(ns[0], 2274LU),
+UA_NODEID_NUMERIC(ns[0], 2253LU),
+UA_NODEID_NUMERIC(ns[0], 47LU),
+UA_QUALIFIEDNAME(ns[0], "ServerDiagnostics"),
+UA_NODEID_NUMERIC(ns[0], 2020LU),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
return retVal;
}
static UA_StatusCode function_namespace0_generated_107_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 11571)
+UA_NODEID_NUMERIC(ns[0], 2274LU)
);
}
-/* MaxNodesPerNodeManagement - ns=0;i=11573 */
+/* EnabledFlag - ns=0;i=2294 */
static UA_StatusCode function_namespace0_generated_108_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_VariableAttributes attr = UA_VariableAttributes_default;
attr.minimumSamplingInterval = 0.000000;
attr.userAccessLevel = 1;
-attr.accessLevel = 1;
+attr.accessLevel = 3;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 7);
-attr.displayName = UA_LOCALIZEDTEXT("", "MaxNodesPerNodeManagement");
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 1LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "EnabledFlag");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 11573),
-UA_NODEID_NUMERIC(ns[0], 11564),
-UA_NODEID_NUMERIC(ns[0], 46),
-UA_QUALIFIEDNAME(ns[0], "MaxNodesPerNodeManagement"),
-UA_NODEID_NUMERIC(ns[0], 68),
+UA_NODEID_NUMERIC(ns[0], 2294LU),
+UA_NODEID_NUMERIC(ns[0], 2274LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
+UA_QUALIFIEDNAME(ns[0], "EnabledFlag"),
+UA_NODEID_NUMERIC(ns[0], 68LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
static UA_StatusCode function_namespace0_generated_108_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 11573)
+UA_NODEID_NUMERIC(ns[0], 2294LU)
);
}
-/* MaxNodesPerBrowse - ns=0;i=11570 */
+/* ServerCapabilities - ns=0;i=2268 */
static UA_StatusCode function_namespace0_generated_109_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
-UA_VariableAttributes attr = UA_VariableAttributes_default;
-attr.minimumSamplingInterval = 0.000000;
-attr.userAccessLevel = 1;
-attr.accessLevel = 1;
-/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 7);
-attr.displayName = UA_LOCALIZEDTEXT("", "MaxNodesPerBrowse");
-retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 11570),
-UA_NODEID_NUMERIC(ns[0], 11564),
-UA_NODEID_NUMERIC(ns[0], 46),
-UA_QUALIFIEDNAME(ns[0], "MaxNodesPerBrowse"),
-UA_NODEID_NUMERIC(ns[0], 68),
-(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+UA_ObjectAttributes attr = UA_ObjectAttributes_default;
+attr.displayName = UA_LOCALIZEDTEXT("", "ServerCapabilities");
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECT,
+UA_NODEID_NUMERIC(ns[0], 2268LU),
+UA_NODEID_NUMERIC(ns[0], 2253LU),
+UA_NODEID_NUMERIC(ns[0], 47LU),
+UA_QUALIFIEDNAME(ns[0], "ServerCapabilities"),
+UA_NODEID_NUMERIC(ns[0], 2013LU),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
return retVal;
}
static UA_StatusCode function_namespace0_generated_109_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 11570)
+UA_NODEID_NUMERIC(ns[0], 2268LU)
);
}
-/* ServerRedundancyType - ns=0;i=2034 */
+/* SoftwareCertificates - ns=0;i=3704 */
static UA_StatusCode function_namespace0_generated_110_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
-UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default;
-attr.displayName = UA_LOCALIZEDTEXT("", "ServerRedundancyType");
-retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECTTYPE,
-UA_NODEID_NUMERIC(ns[0], 2034),
-UA_NODEID_NUMERIC(ns[0], 58),
-UA_NODEID_NUMERIC(ns[0], 45),
-UA_QUALIFIEDNAME(ns[0], "ServerRedundancyType"),
- UA_NODEID_NULL,
-(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL);
+UA_VariableAttributes attr = UA_VariableAttributes_default;
+attr.minimumSamplingInterval = 0.000000;
+attr.userAccessLevel = 1;
+attr.accessLevel = 1;
+attr.valueRank = 1;
+attr.arrayDimensionsSize = 1;
+UA_UInt32 arrayDimensions[1];
+arrayDimensions[0] = 0;
+attr.arrayDimensions = &arrayDimensions[0];
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 344LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "SoftwareCertificates");
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 3704LU),
+UA_NODEID_NUMERIC(ns[0], 2268LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
+UA_QUALIFIEDNAME(ns[0], "SoftwareCertificates"),
+UA_NODEID_NUMERIC(ns[0], 68LU),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
static UA_StatusCode function_namespace0_generated_110_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2034)
+UA_NODEID_NUMERIC(ns[0], 3704LU)
);
}
-/* RedundancySupport - ns=0;i=2035 */
+/* AggregateFunctions - ns=0;i=2997 */
static UA_StatusCode function_namespace0_generated_111_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
-UA_VariableAttributes attr = UA_VariableAttributes_default;
-attr.minimumSamplingInterval = 0.000000;
-attr.userAccessLevel = 1;
-attr.accessLevel = 1;
-/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 851);
-attr.displayName = UA_LOCALIZEDTEXT("", "RedundancySupport");
-retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 2035),
-UA_NODEID_NUMERIC(ns[0], 2034),
-UA_NODEID_NUMERIC(ns[0], 46),
-UA_QUALIFIEDNAME(ns[0], "RedundancySupport"),
-UA_NODEID_NUMERIC(ns[0], 68),
-(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+UA_ObjectAttributes attr = UA_ObjectAttributes_default;
+attr.displayName = UA_LOCALIZEDTEXT("", "AggregateFunctions");
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECT,
+UA_NODEID_NUMERIC(ns[0], 2997LU),
+UA_NODEID_NUMERIC(ns[0], 2268LU),
+UA_NODEID_NUMERIC(ns[0], 47LU),
+UA_QUALIFIEDNAME(ns[0], "AggregateFunctions"),
+UA_NODEID_NUMERIC(ns[0], 61LU),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
return retVal;
}
static UA_StatusCode function_namespace0_generated_111_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2035)
+UA_NODEID_NUMERIC(ns[0], 2997LU)
);
}
-/* VendorServerInfoType - ns=0;i=2033 */
+/* ModellingRules - ns=0;i=2996 */
static UA_StatusCode function_namespace0_generated_112_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
-UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default;
-attr.displayName = UA_LOCALIZEDTEXT("", "VendorServerInfoType");
-retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECTTYPE,
-UA_NODEID_NUMERIC(ns[0], 2033),
-UA_NODEID_NUMERIC(ns[0], 58),
-UA_NODEID_NUMERIC(ns[0], 45),
-UA_QUALIFIEDNAME(ns[0], "VendorServerInfoType"),
- UA_NODEID_NULL,
-(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL);
+UA_ObjectAttributes attr = UA_ObjectAttributes_default;
+attr.displayName = UA_LOCALIZEDTEXT("", "ModellingRules");
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECT,
+UA_NODEID_NUMERIC(ns[0], 2996LU),
+UA_NODEID_NUMERIC(ns[0], 2268LU),
+UA_NODEID_NUMERIC(ns[0], 47LU),
+UA_QUALIFIEDNAME(ns[0], "ModellingRules"),
+UA_NODEID_NUMERIC(ns[0], 61LU),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
return retVal;
}
static UA_StatusCode function_namespace0_generated_112_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2033)
+UA_NODEID_NUMERIC(ns[0], 2996LU)
);
}
-/* ServerDiagnosticsType - ns=0;i=2020 */
+/* MaxHistoryContinuationPoints - ns=0;i=2737 */
static UA_StatusCode function_namespace0_generated_113_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
-UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default;
-attr.displayName = UA_LOCALIZEDTEXT("", "ServerDiagnosticsType");
-retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECTTYPE,
-UA_NODEID_NUMERIC(ns[0], 2020),
-UA_NODEID_NUMERIC(ns[0], 58),
-UA_NODEID_NUMERIC(ns[0], 45),
-UA_QUALIFIEDNAME(ns[0], "ServerDiagnosticsType"),
- UA_NODEID_NULL,
-(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL);
+UA_VariableAttributes attr = UA_VariableAttributes_default;
+attr.minimumSamplingInterval = 0.000000;
+attr.userAccessLevel = 1;
+attr.accessLevel = 1;
+/* Value rank inherited */
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 5LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "MaxHistoryContinuationPoints");
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 2737LU),
+UA_NODEID_NUMERIC(ns[0], 2268LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
+UA_QUALIFIEDNAME(ns[0], "MaxHistoryContinuationPoints"),
+UA_NODEID_NUMERIC(ns[0], 68LU),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
static UA_StatusCode function_namespace0_generated_113_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2020)
+UA_NODEID_NUMERIC(ns[0], 2737LU)
);
}
-/* ServerCapabilitiesType - ns=0;i=2013 */
+/* MaxQueryContinuationPoints - ns=0;i=2736 */
static UA_StatusCode function_namespace0_generated_114_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
-UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default;
-attr.displayName = UA_LOCALIZEDTEXT("", "ServerCapabilitiesType");
-retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECTTYPE,
-UA_NODEID_NUMERIC(ns[0], 2013),
-UA_NODEID_NUMERIC(ns[0], 58),
-UA_NODEID_NUMERIC(ns[0], 45),
-UA_QUALIFIEDNAME(ns[0], "ServerCapabilitiesType"),
- UA_NODEID_NULL,
-(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL);
+UA_VariableAttributes attr = UA_VariableAttributes_default;
+attr.minimumSamplingInterval = 0.000000;
+attr.userAccessLevel = 1;
+attr.accessLevel = 1;
+/* Value rank inherited */
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 5LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "MaxQueryContinuationPoints");
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 2736LU),
+UA_NODEID_NUMERIC(ns[0], 2268LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
+UA_QUALIFIEDNAME(ns[0], "MaxQueryContinuationPoints"),
+UA_NODEID_NUMERIC(ns[0], 68LU),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
static UA_StatusCode function_namespace0_generated_114_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2013)
+UA_NODEID_NUMERIC(ns[0], 2736LU)
);
}
-/* OperationLimits - ns=0;i=11551 */
+/* MaxBrowseContinuationPoints - ns=0;i=2735 */
static UA_StatusCode function_namespace0_generated_115_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
-UA_ObjectAttributes attr = UA_ObjectAttributes_default;
-attr.displayName = UA_LOCALIZEDTEXT("", "OperationLimits");
-retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECT,
-UA_NODEID_NUMERIC(ns[0], 11551),
-UA_NODEID_NUMERIC(ns[0], 2013),
-UA_NODEID_NUMERIC(ns[0], 47),
-UA_QUALIFIEDNAME(ns[0], "OperationLimits"),
-UA_NODEID_NUMERIC(ns[0], 11564),
-(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
+UA_VariableAttributes attr = UA_VariableAttributes_default;
+attr.minimumSamplingInterval = 0.000000;
+attr.userAccessLevel = 1;
+attr.accessLevel = 1;
+/* Value rank inherited */
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 5LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "MaxBrowseContinuationPoints");
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 2735LU),
+UA_NODEID_NUMERIC(ns[0], 2268LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
+UA_QUALIFIEDNAME(ns[0], "MaxBrowseContinuationPoints"),
+UA_NODEID_NUMERIC(ns[0], 68LU),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
static UA_StatusCode function_namespace0_generated_115_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 11551)
+UA_NODEID_NUMERIC(ns[0], 2735LU)
);
}
-/* ServerType - ns=0;i=2004 */
+/* MinSupportedSampleRate - ns=0;i=2272 */
static UA_StatusCode function_namespace0_generated_116_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
-UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default;
-attr.displayName = UA_LOCALIZEDTEXT("", "ServerType");
-retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECTTYPE,
-UA_NODEID_NUMERIC(ns[0], 2004),
-UA_NODEID_NUMERIC(ns[0], 58),
-UA_NODEID_NUMERIC(ns[0], 45),
-UA_QUALIFIEDNAME(ns[0], "ServerType"),
- UA_NODEID_NULL,
-(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL);
+UA_VariableAttributes attr = UA_VariableAttributes_default;
+attr.minimumSamplingInterval = 0.000000;
+attr.userAccessLevel = 1;
+attr.accessLevel = 1;
+/* Value rank inherited */
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 290LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "MinSupportedSampleRate");
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 2272LU),
+UA_NODEID_NUMERIC(ns[0], 2268LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
+UA_QUALIFIEDNAME(ns[0], "MinSupportedSampleRate"),
+UA_NODEID_NUMERIC(ns[0], 68LU),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
static UA_StatusCode function_namespace0_generated_116_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2004)
+UA_NODEID_NUMERIC(ns[0], 2272LU)
);
}
-/* Server - ns=0;i=2253 */
+/* LocaleIdArray - ns=0;i=2271 */
static UA_StatusCode function_namespace0_generated_117_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
-UA_ObjectAttributes attr = UA_ObjectAttributes_default;
-attr.eventNotifier = true;
-attr.displayName = UA_LOCALIZEDTEXT("", "Server");
-retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECT,
-UA_NODEID_NUMERIC(ns[0], 2253),
-UA_NODEID_NUMERIC(ns[0], 85),
-UA_NODEID_NUMERIC(ns[0], 35),
-UA_QUALIFIEDNAME(ns[0], "Server"),
-UA_NODEID_NUMERIC(ns[0], 2004),
-(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
+UA_VariableAttributes attr = UA_VariableAttributes_default;
+attr.minimumSamplingInterval = 0.000000;
+attr.userAccessLevel = 1;
+attr.accessLevel = 1;
+attr.valueRank = 1;
+attr.arrayDimensionsSize = 1;
+UA_UInt32 arrayDimensions[1];
+arrayDimensions[0] = 0;
+attr.arrayDimensions = &arrayDimensions[0];
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 295LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "LocaleIdArray");
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 2271LU),
+UA_NODEID_NUMERIC(ns[0], 2268LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
+UA_QUALIFIEDNAME(ns[0], "LocaleIdArray"),
+UA_NODEID_NUMERIC(ns[0], 68LU),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
static UA_StatusCode function_namespace0_generated_117_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2253)
+UA_NODEID_NUMERIC(ns[0], 2271LU)
);
}
-/* Auditing - ns=0;i=2994 */
+/* ServerProfileArray - ns=0;i=2269 */
static UA_StatusCode function_namespace0_generated_118_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_VariableAttributes attr = UA_VariableAttributes_default;
-attr.minimumSamplingInterval = 1000.000000;
+attr.minimumSamplingInterval = 0.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
-/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 1);
-attr.displayName = UA_LOCALIZEDTEXT("", "Auditing");
+attr.valueRank = 1;
+attr.arrayDimensionsSize = 1;
+UA_UInt32 arrayDimensions[1];
+arrayDimensions[0] = 0;
+attr.arrayDimensions = &arrayDimensions[0];
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 12LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "ServerProfileArray");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 2994),
-UA_NODEID_NUMERIC(ns[0], 2253),
-UA_NODEID_NUMERIC(ns[0], 46),
-UA_QUALIFIEDNAME(ns[0], "Auditing"),
-UA_NODEID_NUMERIC(ns[0], 68),
+UA_NODEID_NUMERIC(ns[0], 2269LU),
+UA_NODEID_NUMERIC(ns[0], 2268LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
+UA_QUALIFIEDNAME(ns[0], "ServerProfileArray"),
+UA_NODEID_NUMERIC(ns[0], 68LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
static UA_StatusCode function_namespace0_generated_118_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2994)
+UA_NODEID_NUMERIC(ns[0], 2269LU)
);
}
-/* ServiceLevel - ns=0;i=2267 */
+/* OperationLimits - ns=0;i=11704 */
static UA_StatusCode function_namespace0_generated_119_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
-UA_VariableAttributes attr = UA_VariableAttributes_default;
-attr.minimumSamplingInterval = 1000.000000;
-attr.userAccessLevel = 1;
-attr.accessLevel = 1;
-/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 3);
-attr.displayName = UA_LOCALIZEDTEXT("", "ServiceLevel");
-retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 2267),
-UA_NODEID_NUMERIC(ns[0], 2253),
-UA_NODEID_NUMERIC(ns[0], 46),
-UA_QUALIFIEDNAME(ns[0], "ServiceLevel"),
-UA_NODEID_NUMERIC(ns[0], 68),
-(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+UA_ObjectAttributes attr = UA_ObjectAttributes_default;
+attr.displayName = UA_LOCALIZEDTEXT("", "OperationLimits");
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECT,
+UA_NODEID_NUMERIC(ns[0], 11704LU),
+UA_NODEID_NUMERIC(ns[0], 2268LU),
+UA_NODEID_NUMERIC(ns[0], 47LU),
+UA_QUALIFIEDNAME(ns[0], "OperationLimits"),
+UA_NODEID_NUMERIC(ns[0], 11564LU),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
return retVal;
}
static UA_StatusCode function_namespace0_generated_119_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2267)
+UA_NODEID_NUMERIC(ns[0], 11704LU)
);
}
-/* VendorServerInfo - ns=0;i=2295 */
+/* MaxMonitoredItemsPerCall - ns=0;i=11714 */
static UA_StatusCode function_namespace0_generated_120_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
-UA_ObjectAttributes attr = UA_ObjectAttributes_default;
-attr.displayName = UA_LOCALIZEDTEXT("", "VendorServerInfo");
-retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECT,
-UA_NODEID_NUMERIC(ns[0], 2295),
-UA_NODEID_NUMERIC(ns[0], 2253),
-UA_NODEID_NUMERIC(ns[0], 47),
-UA_QUALIFIEDNAME(ns[0], "VendorServerInfo"),
-UA_NODEID_NUMERIC(ns[0], 2033),
-(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
+UA_VariableAttributes attr = UA_VariableAttributes_default;
+attr.minimumSamplingInterval = 0.000000;
+attr.userAccessLevel = 1;
+attr.accessLevel = 1;
+/* Value rank inherited */
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 7LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "MaxMonitoredItemsPerCall");
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 11714LU),
+UA_NODEID_NUMERIC(ns[0], 11704LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
+UA_QUALIFIEDNAME(ns[0], "MaxMonitoredItemsPerCall"),
+UA_NODEID_NUMERIC(ns[0], 68LU),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
static UA_StatusCode function_namespace0_generated_120_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2295)
+UA_NODEID_NUMERIC(ns[0], 11714LU)
);
}
-/* NamespaceArray - ns=0;i=2255 */
+/* MaxNodesPerNodeManagement - ns=0;i=11713 */
static UA_StatusCode function_namespace0_generated_121_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_VariableAttributes attr = UA_VariableAttributes_default;
-attr.minimumSamplingInterval = 1000.000000;
+attr.minimumSamplingInterval = 0.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
-attr.valueRank = 1;
-attr.arrayDimensionsSize = 1;
-UA_UInt32 arrayDimensions[1];
-arrayDimensions[0] = 0;
-attr.arrayDimensions = &arrayDimensions[0];
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 12);
-attr.displayName = UA_LOCALIZEDTEXT("", "NamespaceArray");
+/* Value rank inherited */
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 7LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "MaxNodesPerNodeManagement");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 2255),
-UA_NODEID_NUMERIC(ns[0], 2253),
-UA_NODEID_NUMERIC(ns[0], 46),
-UA_QUALIFIEDNAME(ns[0], "NamespaceArray"),
-UA_NODEID_NUMERIC(ns[0], 68),
+UA_NODEID_NUMERIC(ns[0], 11713LU),
+UA_NODEID_NUMERIC(ns[0], 11704LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
+UA_QUALIFIEDNAME(ns[0], "MaxNodesPerNodeManagement"),
+UA_NODEID_NUMERIC(ns[0], 68LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
static UA_StatusCode function_namespace0_generated_121_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2255)
+UA_NODEID_NUMERIC(ns[0], 11713LU)
);
}
-/* GetMonitoredItems - ns=0;i=11492 */
+/* MaxNodesPerTranslateBrowsePathsToNodeIds - ns=0;i=11712 */
static UA_StatusCode function_namespace0_generated_122_begin(UA_Server *server, UA_UInt16* ns) {
-#ifdef UA_ENABLE_METHODCALLS
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
-UA_MethodAttributes attr = UA_MethodAttributes_default;
-attr.executable = true;
-attr.userExecutable = true;
-attr.displayName = UA_LOCALIZEDTEXT("", "GetMonitoredItems");
-retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_METHOD,
-UA_NODEID_NUMERIC(ns[0], 11492),
-UA_NODEID_NUMERIC(ns[0], 2253),
-UA_NODEID_NUMERIC(ns[0], 47),
-UA_QUALIFIEDNAME(ns[0], "GetMonitoredItems"),
- UA_NODEID_NULL,
-(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_METHODATTRIBUTES],NULL, NULL);
+UA_VariableAttributes attr = UA_VariableAttributes_default;
+attr.minimumSamplingInterval = 0.000000;
+attr.userAccessLevel = 1;
+attr.accessLevel = 1;
+/* Value rank inherited */
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 7LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "MaxNodesPerTranslateBrowsePathsToNodeIds");
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 11712LU),
+UA_NODEID_NUMERIC(ns[0], 11704LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
+UA_QUALIFIEDNAME(ns[0], "MaxNodesPerTranslateBrowsePathsToNodeIds"),
+UA_NODEID_NUMERIC(ns[0], 68LU),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
-#else
-return UA_STATUSCODE_GOOD;
-#endif /* UA_ENABLE_METHODCALLS */
}
static UA_StatusCode function_namespace0_generated_122_finish(UA_Server *server, UA_UInt16* ns) {
-#ifdef UA_ENABLE_METHODCALLS
-return UA_Server_addMethodNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 11492)
-, NULL, 0, NULL, 0, NULL);
-#else
-return UA_STATUSCODE_GOOD;
-#endif /* UA_ENABLE_METHODCALLS */
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 11712LU)
+);
}
-/* OutputArguments - ns=0;i=11494 */
+/* MaxNodesPerRegisterNodes - ns=0;i=11711 */
static UA_StatusCode function_namespace0_generated_123_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
@@ -49393,54 +55079,27 @@ UA_VariableAttributes attr = UA_VariableAttributes_default;
attr.minimumSamplingInterval = 0.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
-attr.valueRank = 1;
-attr.arrayDimensionsSize = 1;
-UA_UInt32 arrayDimensions[1];
-arrayDimensions[0] = 0;
-attr.arrayDimensions = &arrayDimensions[0];
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 296);
-UA_Argument variablenode_ns_0_i_11494_variant_DataContents[2];
-
-UA_init(&variablenode_ns_0_i_11494_variant_DataContents[0], &UA_TYPES[UA_TYPES_ARGUMENT]);
-variablenode_ns_0_i_11494_variant_DataContents[0].name = UA_STRING("ServerHandles");
-variablenode_ns_0_i_11494_variant_DataContents[0].dataType = UA_NODEID_NUMERIC(ns[0], 7);
-variablenode_ns_0_i_11494_variant_DataContents[0].valueRank = (UA_Int32) 1;
-UA_STACKARRAY(UA_UInt32, variablenode_ns_0_i_11494_variant_DataContents0_arrayDimensions, 1);
-UA_init(variablenode_ns_0_i_11494_variant_DataContents0_arrayDimensions, &UA_TYPES[UA_TYPES_UINT32]);
-variablenode_ns_0_i_11494_variant_DataContents0_arrayDimensions[0] = (UA_UInt32) 0;
-variablenode_ns_0_i_11494_variant_DataContents[0].arrayDimensionsSize = 1;
-variablenode_ns_0_i_11494_variant_DataContents[0].arrayDimensions = variablenode_ns_0_i_11494_variant_DataContents0_arrayDimensions;
-
-UA_init(&variablenode_ns_0_i_11494_variant_DataContents[1], &UA_TYPES[UA_TYPES_ARGUMENT]);
-variablenode_ns_0_i_11494_variant_DataContents[1].name = UA_STRING("ClientHandles");
-variablenode_ns_0_i_11494_variant_DataContents[1].dataType = UA_NODEID_NUMERIC(ns[0], 7);
-variablenode_ns_0_i_11494_variant_DataContents[1].valueRank = (UA_Int32) 1;
-UA_STACKARRAY(UA_UInt32, variablenode_ns_0_i_11494_variant_DataContents1_arrayDimensions, 1);
-UA_init(variablenode_ns_0_i_11494_variant_DataContents1_arrayDimensions, &UA_TYPES[UA_TYPES_UINT32]);
-variablenode_ns_0_i_11494_variant_DataContents1_arrayDimensions[0] = (UA_UInt32) 0;
-variablenode_ns_0_i_11494_variant_DataContents[1].arrayDimensionsSize = 1;
-variablenode_ns_0_i_11494_variant_DataContents[1].arrayDimensions = variablenode_ns_0_i_11494_variant_DataContents1_arrayDimensions;
-UA_Variant_setArray(&attr.value, &variablenode_ns_0_i_11494_variant_DataContents, (UA_Int32) 2, &UA_TYPES[UA_TYPES_ARGUMENT]);
-attr.displayName = UA_LOCALIZEDTEXT("", "OutputArguments");
+/* Value rank inherited */
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 7LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "MaxNodesPerRegisterNodes");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 11494),
-UA_NODEID_NUMERIC(ns[0], 11492),
-UA_NODEID_NUMERIC(ns[0], 46),
-UA_QUALIFIEDNAME(ns[0], "OutputArguments"),
-UA_NODEID_NUMERIC(ns[0], 68),
+UA_NODEID_NUMERIC(ns[0], 11711LU),
+UA_NODEID_NUMERIC(ns[0], 11704LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
+UA_QUALIFIEDNAME(ns[0], "MaxNodesPerRegisterNodes"),
+UA_NODEID_NUMERIC(ns[0], 68LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
-
-
return retVal;
}
static UA_StatusCode function_namespace0_generated_123_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 11494)
+UA_NODEID_NUMERIC(ns[0], 11711LU)
);
}
-/* InputArguments - ns=0;i=11493 */
+/* MaxNodesPerBrowse - ns=0;i=11710 */
static UA_StatusCode function_namespace0_generated_124_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
@@ -49448,66 +55107,55 @@ UA_VariableAttributes attr = UA_VariableAttributes_default;
attr.minimumSamplingInterval = 0.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
-attr.valueRank = 1;
-attr.arrayDimensionsSize = 1;
-UA_UInt32 arrayDimensions[1];
-arrayDimensions[0] = 0;
-attr.arrayDimensions = &arrayDimensions[0];
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 296);
-UA_Argument variablenode_ns_0_i_11493_variant_DataContents[1];
-
-UA_init(&variablenode_ns_0_i_11493_variant_DataContents[0], &UA_TYPES[UA_TYPES_ARGUMENT]);
-variablenode_ns_0_i_11493_variant_DataContents[0].name = UA_STRING("SubscriptionId");
-variablenode_ns_0_i_11493_variant_DataContents[0].dataType = UA_NODEID_NUMERIC(ns[0], 7);
-variablenode_ns_0_i_11493_variant_DataContents[0].valueRank = (UA_Int32) -1;
-UA_Variant_setArray(&attr.value, &variablenode_ns_0_i_11493_variant_DataContents, (UA_Int32) 1, &UA_TYPES[UA_TYPES_ARGUMENT]);
-attr.displayName = UA_LOCALIZEDTEXT("", "InputArguments");
+/* Value rank inherited */
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 7LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "MaxNodesPerBrowse");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 11493),
-UA_NODEID_NUMERIC(ns[0], 11492),
-UA_NODEID_NUMERIC(ns[0], 46),
-UA_QUALIFIEDNAME(ns[0], "InputArguments"),
-UA_NODEID_NUMERIC(ns[0], 68),
+UA_NODEID_NUMERIC(ns[0], 11710LU),
+UA_NODEID_NUMERIC(ns[0], 11704LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
+UA_QUALIFIEDNAME(ns[0], "MaxNodesPerBrowse"),
+UA_NODEID_NUMERIC(ns[0], 68LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
-
return retVal;
}
static UA_StatusCode function_namespace0_generated_124_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 11493)
+UA_NODEID_NUMERIC(ns[0], 11710LU)
);
}
-/* ServerStatus - ns=0;i=2256 */
+/* MaxNodesPerMethodCall - ns=0;i=11709 */
static UA_StatusCode function_namespace0_generated_125_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_VariableAttributes attr = UA_VariableAttributes_default;
-attr.minimumSamplingInterval = 1000.000000;
+attr.minimumSamplingInterval = 0.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 862);
-attr.displayName = UA_LOCALIZEDTEXT("", "ServerStatus");
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 7LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "MaxNodesPerMethodCall");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 2256),
-UA_NODEID_NUMERIC(ns[0], 2253),
-UA_NODEID_NUMERIC(ns[0], 47),
-UA_QUALIFIEDNAME(ns[0], "ServerStatus"),
-UA_NODEID_NUMERIC(ns[0], 2138),
+UA_NODEID_NUMERIC(ns[0], 11709LU),
+UA_NODEID_NUMERIC(ns[0], 11704LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
+UA_QUALIFIEDNAME(ns[0], "MaxNodesPerMethodCall"),
+UA_NODEID_NUMERIC(ns[0], 68LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
static UA_StatusCode function_namespace0_generated_125_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2256)
+UA_NODEID_NUMERIC(ns[0], 11709LU)
);
}
-/* ShutdownReason - ns=0;i=2993 */
+/* MaxNodesPerWrite - ns=0;i=11707 */
static UA_StatusCode function_namespace0_generated_126_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
@@ -49516,26 +55164,26 @@ attr.minimumSamplingInterval = 0.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 21);
-attr.displayName = UA_LOCALIZEDTEXT("", "ShutdownReason");
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 7LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "MaxNodesPerWrite");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 2993),
-UA_NODEID_NUMERIC(ns[0], 2256),
-UA_NODEID_NUMERIC(ns[0], 47),
-UA_QUALIFIEDNAME(ns[0], "ShutdownReason"),
-UA_NODEID_NUMERIC(ns[0], 63),
+UA_NODEID_NUMERIC(ns[0], 11707LU),
+UA_NODEID_NUMERIC(ns[0], 11704LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
+UA_QUALIFIEDNAME(ns[0], "MaxNodesPerWrite"),
+UA_NODEID_NUMERIC(ns[0], 68LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
static UA_StatusCode function_namespace0_generated_126_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2993)
+UA_NODEID_NUMERIC(ns[0], 11707LU)
);
}
-/* BuildInfo - ns=0;i=2260 */
+/* MaxNodesPerRead - ns=0;i=11705 */
static UA_StatusCode function_namespace0_generated_127_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
@@ -49544,194 +55192,188 @@ attr.minimumSamplingInterval = 0.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 338);
-attr.displayName = UA_LOCALIZEDTEXT("", "BuildInfo");
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 7LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "MaxNodesPerRead");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 2260),
-UA_NODEID_NUMERIC(ns[0], 2256),
-UA_NODEID_NUMERIC(ns[0], 47),
-UA_QUALIFIEDNAME(ns[0], "BuildInfo"),
-UA_NODEID_NUMERIC(ns[0], 3051),
+UA_NODEID_NUMERIC(ns[0], 11705LU),
+UA_NODEID_NUMERIC(ns[0], 11704LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
+UA_QUALIFIEDNAME(ns[0], "MaxNodesPerRead"),
+UA_NODEID_NUMERIC(ns[0], 68LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
static UA_StatusCode function_namespace0_generated_127_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2260)
+UA_NODEID_NUMERIC(ns[0], 11705LU)
);
}
-/* ProductUri - ns=0;i=2262 */
+/* HistoryServerCapabilities - ns=0;i=11192 */
static UA_StatusCode function_namespace0_generated_128_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
-UA_VariableAttributes attr = UA_VariableAttributes_default;
-attr.minimumSamplingInterval = 1000.000000;
-attr.userAccessLevel = 1;
-attr.accessLevel = 1;
-/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 12);
-attr.displayName = UA_LOCALIZEDTEXT("", "ProductUri");
-retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 2262),
-UA_NODEID_NUMERIC(ns[0], 2260),
-UA_NODEID_NUMERIC(ns[0], 47),
-UA_QUALIFIEDNAME(ns[0], "ProductUri"),
-UA_NODEID_NUMERIC(ns[0], 63),
-(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+UA_ObjectAttributes attr = UA_ObjectAttributes_default;
+attr.displayName = UA_LOCALIZEDTEXT("", "HistoryServerCapabilities");
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECT,
+UA_NODEID_NUMERIC(ns[0], 11192LU),
+UA_NODEID_NUMERIC(ns[0], 2268LU),
+UA_NODEID_NUMERIC(ns[0], 47LU),
+UA_QUALIFIEDNAME(ns[0], "HistoryServerCapabilities"),
+UA_NODEID_NUMERIC(ns[0], 2330LU),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
return retVal;
}
static UA_StatusCode function_namespace0_generated_128_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2262)
+UA_NODEID_NUMERIC(ns[0], 11192LU)
);
}
-/* ProductName - ns=0;i=2261 */
+/* DeleteEventCapability - ns=0;i=11502 */
static UA_StatusCode function_namespace0_generated_129_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_VariableAttributes attr = UA_VariableAttributes_default;
-attr.minimumSamplingInterval = 1000.000000;
+attr.minimumSamplingInterval = 0.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 12);
-attr.displayName = UA_LOCALIZEDTEXT("", "ProductName");
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 1LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "DeleteEventCapability");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 2261),
-UA_NODEID_NUMERIC(ns[0], 2260),
-UA_NODEID_NUMERIC(ns[0], 47),
-UA_QUALIFIEDNAME(ns[0], "ProductName"),
-UA_NODEID_NUMERIC(ns[0], 63),
+UA_NODEID_NUMERIC(ns[0], 11502LU),
+UA_NODEID_NUMERIC(ns[0], 11192LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
+UA_QUALIFIEDNAME(ns[0], "DeleteEventCapability"),
+UA_NODEID_NUMERIC(ns[0], 68LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
static UA_StatusCode function_namespace0_generated_129_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2261)
+UA_NODEID_NUMERIC(ns[0], 11502LU)
);
}
-/* BuildDate - ns=0;i=2266 */
+/* UpdateEventCapability - ns=0;i=11283 */
static UA_StatusCode function_namespace0_generated_130_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_VariableAttributes attr = UA_VariableAttributes_default;
-attr.minimumSamplingInterval = 1000.000000;
+attr.minimumSamplingInterval = 0.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 294);
-attr.displayName = UA_LOCALIZEDTEXT("", "BuildDate");
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 1LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "UpdateEventCapability");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 2266),
-UA_NODEID_NUMERIC(ns[0], 2260),
-UA_NODEID_NUMERIC(ns[0], 47),
-UA_QUALIFIEDNAME(ns[0], "BuildDate"),
-UA_NODEID_NUMERIC(ns[0], 63),
+UA_NODEID_NUMERIC(ns[0], 11283LU),
+UA_NODEID_NUMERIC(ns[0], 11192LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
+UA_QUALIFIEDNAME(ns[0], "UpdateEventCapability"),
+UA_NODEID_NUMERIC(ns[0], 68LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
static UA_StatusCode function_namespace0_generated_130_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2266)
+UA_NODEID_NUMERIC(ns[0], 11283LU)
);
}
-/* BuildNumber - ns=0;i=2265 */
+/* ReplaceEventCapability - ns=0;i=11282 */
static UA_StatusCode function_namespace0_generated_131_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_VariableAttributes attr = UA_VariableAttributes_default;
-attr.minimumSamplingInterval = 1000.000000;
+attr.minimumSamplingInterval = 0.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 12);
-attr.displayName = UA_LOCALIZEDTEXT("", "BuildNumber");
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 1LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "ReplaceEventCapability");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 2265),
-UA_NODEID_NUMERIC(ns[0], 2260),
-UA_NODEID_NUMERIC(ns[0], 47),
-UA_QUALIFIEDNAME(ns[0], "BuildNumber"),
-UA_NODEID_NUMERIC(ns[0], 63),
+UA_NODEID_NUMERIC(ns[0], 11282LU),
+UA_NODEID_NUMERIC(ns[0], 11192LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
+UA_QUALIFIEDNAME(ns[0], "ReplaceEventCapability"),
+UA_NODEID_NUMERIC(ns[0], 68LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
static UA_StatusCode function_namespace0_generated_131_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2265)
+UA_NODEID_NUMERIC(ns[0], 11282LU)
);
}
-/* ManufacturerName - ns=0;i=2263 */
+/* InsertEventCapability - ns=0;i=11281 */
static UA_StatusCode function_namespace0_generated_132_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_VariableAttributes attr = UA_VariableAttributes_default;
-attr.minimumSamplingInterval = 1000.000000;
+attr.minimumSamplingInterval = 0.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 12);
-attr.displayName = UA_LOCALIZEDTEXT("", "ManufacturerName");
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 1LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "InsertEventCapability");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 2263),
-UA_NODEID_NUMERIC(ns[0], 2260),
-UA_NODEID_NUMERIC(ns[0], 47),
-UA_QUALIFIEDNAME(ns[0], "ManufacturerName"),
-UA_NODEID_NUMERIC(ns[0], 63),
+UA_NODEID_NUMERIC(ns[0], 11281LU),
+UA_NODEID_NUMERIC(ns[0], 11192LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
+UA_QUALIFIEDNAME(ns[0], "InsertEventCapability"),
+UA_NODEID_NUMERIC(ns[0], 68LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
static UA_StatusCode function_namespace0_generated_132_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2263)
+UA_NODEID_NUMERIC(ns[0], 11281LU)
);
}
-/* SoftwareVersion - ns=0;i=2264 */
+/* InsertAnnotationCapability - ns=0;i=11275 */
static UA_StatusCode function_namespace0_generated_133_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_VariableAttributes attr = UA_VariableAttributes_default;
-attr.minimumSamplingInterval = 1000.000000;
+attr.minimumSamplingInterval = 0.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 12);
-attr.displayName = UA_LOCALIZEDTEXT("", "SoftwareVersion");
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 1LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "InsertAnnotationCapability");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 2264),
-UA_NODEID_NUMERIC(ns[0], 2260),
-UA_NODEID_NUMERIC(ns[0], 47),
-UA_QUALIFIEDNAME(ns[0], "SoftwareVersion"),
-UA_NODEID_NUMERIC(ns[0], 63),
+UA_NODEID_NUMERIC(ns[0], 11275LU),
+UA_NODEID_NUMERIC(ns[0], 11192LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
+UA_QUALIFIEDNAME(ns[0], "InsertAnnotationCapability"),
+UA_NODEID_NUMERIC(ns[0], 68LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
static UA_StatusCode function_namespace0_generated_133_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2264)
+UA_NODEID_NUMERIC(ns[0], 11275LU)
);
}
-/* SecondsTillShutdown - ns=0;i=2992 */
+/* MaxReturnEventValues - ns=0;i=11274 */
static UA_StatusCode function_namespace0_generated_134_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
@@ -49740,26 +55382,26 @@ attr.minimumSamplingInterval = 0.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 7);
-attr.displayName = UA_LOCALIZEDTEXT("", "SecondsTillShutdown");
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 7LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "MaxReturnEventValues");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 2992),
-UA_NODEID_NUMERIC(ns[0], 2256),
-UA_NODEID_NUMERIC(ns[0], 47),
-UA_QUALIFIEDNAME(ns[0], "SecondsTillShutdown"),
-UA_NODEID_NUMERIC(ns[0], 63),
+UA_NODEID_NUMERIC(ns[0], 11274LU),
+UA_NODEID_NUMERIC(ns[0], 11192LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
+UA_QUALIFIEDNAME(ns[0], "MaxReturnEventValues"),
+UA_NODEID_NUMERIC(ns[0], 68LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
static UA_StatusCode function_namespace0_generated_134_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2992)
+UA_NODEID_NUMERIC(ns[0], 11274LU)
);
}
-/* StartTime - ns=0;i=2257 */
+/* MaxReturnDataValues - ns=0;i=11273 */
static UA_StatusCode function_namespace0_generated_135_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
@@ -49768,26 +55410,26 @@ attr.minimumSamplingInterval = 0.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 294);
-attr.displayName = UA_LOCALIZEDTEXT("", "StartTime");
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 7LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "MaxReturnDataValues");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 2257),
-UA_NODEID_NUMERIC(ns[0], 2256),
-UA_NODEID_NUMERIC(ns[0], 47),
-UA_QUALIFIEDNAME(ns[0], "StartTime"),
-UA_NODEID_NUMERIC(ns[0], 63),
+UA_NODEID_NUMERIC(ns[0], 11273LU),
+UA_NODEID_NUMERIC(ns[0], 11192LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
+UA_QUALIFIEDNAME(ns[0], "MaxReturnDataValues"),
+UA_NODEID_NUMERIC(ns[0], 68LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
static UA_StatusCode function_namespace0_generated_135_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2257)
+UA_NODEID_NUMERIC(ns[0], 11273LU)
);
}
-/* CurrentTime - ns=0;i=2258 */
+/* AccessHistoryEventsCapability - ns=0;i=11242 */
static UA_StatusCode function_namespace0_generated_136_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
@@ -49796,76 +55438,76 @@ attr.minimumSamplingInterval = 0.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 294);
-attr.displayName = UA_LOCALIZEDTEXT("", "CurrentTime");
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 1LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "AccessHistoryEventsCapability");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 2258),
-UA_NODEID_NUMERIC(ns[0], 2256),
-UA_NODEID_NUMERIC(ns[0], 47),
-UA_QUALIFIEDNAME(ns[0], "CurrentTime"),
-UA_NODEID_NUMERIC(ns[0], 63),
+UA_NODEID_NUMERIC(ns[0], 11242LU),
+UA_NODEID_NUMERIC(ns[0], 11192LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
+UA_QUALIFIEDNAME(ns[0], "AccessHistoryEventsCapability"),
+UA_NODEID_NUMERIC(ns[0], 68LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
static UA_StatusCode function_namespace0_generated_136_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2258)
+UA_NODEID_NUMERIC(ns[0], 11242LU)
);
}
-/* State - ns=0;i=2259 */
+/* AggregateFunctions - ns=0;i=11201 */
static UA_StatusCode function_namespace0_generated_137_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
-UA_VariableAttributes attr = UA_VariableAttributes_default;
-attr.minimumSamplingInterval = 0.000000;
-attr.userAccessLevel = 1;
-attr.accessLevel = 1;
-/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 852);
-attr.displayName = UA_LOCALIZEDTEXT("", "State");
-retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 2259),
-UA_NODEID_NUMERIC(ns[0], 2256),
-UA_NODEID_NUMERIC(ns[0], 47),
-UA_QUALIFIEDNAME(ns[0], "State"),
-UA_NODEID_NUMERIC(ns[0], 63),
-(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+UA_ObjectAttributes attr = UA_ObjectAttributes_default;
+attr.displayName = UA_LOCALIZEDTEXT("", "AggregateFunctions");
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECT,
+UA_NODEID_NUMERIC(ns[0], 11201LU),
+UA_NODEID_NUMERIC(ns[0], 11192LU),
+UA_NODEID_NUMERIC(ns[0], 47LU),
+UA_QUALIFIEDNAME(ns[0], "AggregateFunctions"),
+UA_NODEID_NUMERIC(ns[0], 61LU),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
return retVal;
}
static UA_StatusCode function_namespace0_generated_137_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2259)
+UA_NODEID_NUMERIC(ns[0], 11201LU)
);
}
-/* ServerDiagnostics - ns=0;i=2274 */
+/* DeleteAtTimeCapability - ns=0;i=11200 */
static UA_StatusCode function_namespace0_generated_138_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
-UA_ObjectAttributes attr = UA_ObjectAttributes_default;
-attr.displayName = UA_LOCALIZEDTEXT("", "ServerDiagnostics");
-retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECT,
-UA_NODEID_NUMERIC(ns[0], 2274),
-UA_NODEID_NUMERIC(ns[0], 2253),
-UA_NODEID_NUMERIC(ns[0], 47),
-UA_QUALIFIEDNAME(ns[0], "ServerDiagnostics"),
-UA_NODEID_NUMERIC(ns[0], 2020),
-(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
+UA_VariableAttributes attr = UA_VariableAttributes_default;
+attr.minimumSamplingInterval = 0.000000;
+attr.userAccessLevel = 1;
+attr.accessLevel = 1;
+/* Value rank inherited */
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 1LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "DeleteAtTimeCapability");
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 11200LU),
+UA_NODEID_NUMERIC(ns[0], 11192LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
+UA_QUALIFIEDNAME(ns[0], "DeleteAtTimeCapability"),
+UA_NODEID_NUMERIC(ns[0], 68LU),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
static UA_StatusCode function_namespace0_generated_138_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2274)
+UA_NODEID_NUMERIC(ns[0], 11200LU)
);
}
-/* ServerDiagnosticsSummary - ns=0;i=2275 */
+/* DeleteRawCapability - ns=0;i=11199 */
static UA_StatusCode function_namespace0_generated_139_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
@@ -49874,26 +55516,26 @@ attr.minimumSamplingInterval = 0.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 859);
-attr.displayName = UA_LOCALIZEDTEXT("", "ServerDiagnosticsSummary");
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 1LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "DeleteRawCapability");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 2275),
-UA_NODEID_NUMERIC(ns[0], 2274),
-UA_NODEID_NUMERIC(ns[0], 47),
-UA_QUALIFIEDNAME(ns[0], "ServerDiagnosticsSummary"),
-UA_NODEID_NUMERIC(ns[0], 2150),
+UA_NODEID_NUMERIC(ns[0], 11199LU),
+UA_NODEID_NUMERIC(ns[0], 11192LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
+UA_QUALIFIEDNAME(ns[0], "DeleteRawCapability"),
+UA_NODEID_NUMERIC(ns[0], 68LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
static UA_StatusCode function_namespace0_generated_139_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2275)
+UA_NODEID_NUMERIC(ns[0], 11199LU)
);
}
-/* RejectedSessionCount - ns=0;i=3705 */
+/* UpdateDataCapability - ns=0;i=11198 */
static UA_StatusCode function_namespace0_generated_140_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
@@ -49902,26 +55544,26 @@ attr.minimumSamplingInterval = 0.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 7);
-attr.displayName = UA_LOCALIZEDTEXT("", "RejectedSessionCount");
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 1LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "UpdateDataCapability");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 3705),
-UA_NODEID_NUMERIC(ns[0], 2275),
-UA_NODEID_NUMERIC(ns[0], 47),
-UA_QUALIFIEDNAME(ns[0], "RejectedSessionCount"),
-UA_NODEID_NUMERIC(ns[0], 63),
+UA_NODEID_NUMERIC(ns[0], 11198LU),
+UA_NODEID_NUMERIC(ns[0], 11192LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
+UA_QUALIFIEDNAME(ns[0], "UpdateDataCapability"),
+UA_NODEID_NUMERIC(ns[0], 68LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
static UA_StatusCode function_namespace0_generated_140_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 3705)
+UA_NODEID_NUMERIC(ns[0], 11198LU)
);
}
-/* SessionTimeoutCount - ns=0;i=2281 */
+/* ReplaceDataCapability - ns=0;i=11197 */
static UA_StatusCode function_namespace0_generated_141_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
@@ -49930,26 +55572,26 @@ attr.minimumSamplingInterval = 0.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 7);
-attr.displayName = UA_LOCALIZEDTEXT("", "SessionTimeoutCount");
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 1LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "ReplaceDataCapability");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 2281),
-UA_NODEID_NUMERIC(ns[0], 2275),
-UA_NODEID_NUMERIC(ns[0], 47),
-UA_QUALIFIEDNAME(ns[0], "SessionTimeoutCount"),
-UA_NODEID_NUMERIC(ns[0], 63),
+UA_NODEID_NUMERIC(ns[0], 11197LU),
+UA_NODEID_NUMERIC(ns[0], 11192LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
+UA_QUALIFIEDNAME(ns[0], "ReplaceDataCapability"),
+UA_NODEID_NUMERIC(ns[0], 68LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
static UA_StatusCode function_namespace0_generated_141_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2281)
+UA_NODEID_NUMERIC(ns[0], 11197LU)
);
}
-/* CumulatedSessionCount - ns=0;i=2278 */
+/* InsertDataCapability - ns=0;i=11196 */
static UA_StatusCode function_namespace0_generated_142_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
@@ -49958,26 +55600,26 @@ attr.minimumSamplingInterval = 0.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 7);
-attr.displayName = UA_LOCALIZEDTEXT("", "CumulatedSessionCount");
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 1LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "InsertDataCapability");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 2278),
-UA_NODEID_NUMERIC(ns[0], 2275),
-UA_NODEID_NUMERIC(ns[0], 47),
-UA_QUALIFIEDNAME(ns[0], "CumulatedSessionCount"),
-UA_NODEID_NUMERIC(ns[0], 63),
+UA_NODEID_NUMERIC(ns[0], 11196LU),
+UA_NODEID_NUMERIC(ns[0], 11192LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
+UA_QUALIFIEDNAME(ns[0], "InsertDataCapability"),
+UA_NODEID_NUMERIC(ns[0], 68LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
static UA_StatusCode function_namespace0_generated_142_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2278)
+UA_NODEID_NUMERIC(ns[0], 11196LU)
);
}
-/* PublishingIntervalCount - ns=0;i=2284 */
+/* AccessHistoryDataCapability - ns=0;i=11193 */
static UA_StatusCode function_namespace0_generated_143_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
@@ -49986,82 +55628,82 @@ attr.minimumSamplingInterval = 0.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 7);
-attr.displayName = UA_LOCALIZEDTEXT("", "PublishingIntervalCount");
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 1LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "AccessHistoryDataCapability");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 2284),
-UA_NODEID_NUMERIC(ns[0], 2275),
-UA_NODEID_NUMERIC(ns[0], 47),
-UA_QUALIFIEDNAME(ns[0], "PublishingIntervalCount"),
-UA_NODEID_NUMERIC(ns[0], 63),
+UA_NODEID_NUMERIC(ns[0], 11193LU),
+UA_NODEID_NUMERIC(ns[0], 11192LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
+UA_QUALIFIEDNAME(ns[0], "AccessHistoryDataCapability"),
+UA_NODEID_NUMERIC(ns[0], 68LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
static UA_StatusCode function_namespace0_generated_143_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2284)
+UA_NODEID_NUMERIC(ns[0], 11193LU)
);
}
-/* SecurityRejectedRequestsCount - ns=0;i=2287 */
+/* ServiceLevel - ns=0;i=2267 */
static UA_StatusCode function_namespace0_generated_144_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_VariableAttributes attr = UA_VariableAttributes_default;
-attr.minimumSamplingInterval = 0.000000;
+attr.minimumSamplingInterval = 1000.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 7);
-attr.displayName = UA_LOCALIZEDTEXT("", "SecurityRejectedRequestsCount");
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 3LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "ServiceLevel");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 2287),
-UA_NODEID_NUMERIC(ns[0], 2275),
-UA_NODEID_NUMERIC(ns[0], 47),
-UA_QUALIFIEDNAME(ns[0], "SecurityRejectedRequestsCount"),
-UA_NODEID_NUMERIC(ns[0], 63),
+UA_NODEID_NUMERIC(ns[0], 2267LU),
+UA_NODEID_NUMERIC(ns[0], 2253LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
+UA_QUALIFIEDNAME(ns[0], "ServiceLevel"),
+UA_NODEID_NUMERIC(ns[0], 68LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
static UA_StatusCode function_namespace0_generated_144_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2287)
+UA_NODEID_NUMERIC(ns[0], 2267LU)
);
}
-/* SessionAbortCount - ns=0;i=2282 */
+/* ServerStatus - ns=0;i=2256 */
static UA_StatusCode function_namespace0_generated_145_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_VariableAttributes attr = UA_VariableAttributes_default;
-attr.minimumSamplingInterval = 0.000000;
+attr.minimumSamplingInterval = 1000.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 7);
-attr.displayName = UA_LOCALIZEDTEXT("", "SessionAbortCount");
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 862LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "ServerStatus");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 2282),
-UA_NODEID_NUMERIC(ns[0], 2275),
-UA_NODEID_NUMERIC(ns[0], 47),
-UA_QUALIFIEDNAME(ns[0], "SessionAbortCount"),
-UA_NODEID_NUMERIC(ns[0], 63),
+UA_NODEID_NUMERIC(ns[0], 2256LU),
+UA_NODEID_NUMERIC(ns[0], 2253LU),
+UA_NODEID_NUMERIC(ns[0], 47LU),
+UA_QUALIFIEDNAME(ns[0], "ServerStatus"),
+UA_NODEID_NUMERIC(ns[0], 2138LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
static UA_StatusCode function_namespace0_generated_145_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2282)
+UA_NODEID_NUMERIC(ns[0], 2256LU)
);
}
-/* RejectedRequestsCount - ns=0;i=2288 */
+/* ShutdownReason - ns=0;i=2993 */
static UA_StatusCode function_namespace0_generated_146_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
@@ -50070,26 +55712,26 @@ attr.minimumSamplingInterval = 0.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 7);
-attr.displayName = UA_LOCALIZEDTEXT("", "RejectedRequestsCount");
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 21LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "ShutdownReason");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 2288),
-UA_NODEID_NUMERIC(ns[0], 2275),
-UA_NODEID_NUMERIC(ns[0], 47),
-UA_QUALIFIEDNAME(ns[0], "RejectedRequestsCount"),
-UA_NODEID_NUMERIC(ns[0], 63),
+UA_NODEID_NUMERIC(ns[0], 2993LU),
+UA_NODEID_NUMERIC(ns[0], 2256LU),
+UA_NODEID_NUMERIC(ns[0], 47LU),
+UA_QUALIFIEDNAME(ns[0], "ShutdownReason"),
+UA_NODEID_NUMERIC(ns[0], 63LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
static UA_StatusCode function_namespace0_generated_146_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2288)
+UA_NODEID_NUMERIC(ns[0], 2993LU)
);
}
-/* ServerViewCount - ns=0;i=2276 */
+/* SecondsTillShutdown - ns=0;i=2992 */
static UA_StatusCode function_namespace0_generated_147_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
@@ -50098,26 +55740,26 @@ attr.minimumSamplingInterval = 0.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 7);
-attr.displayName = UA_LOCALIZEDTEXT("", "ServerViewCount");
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 7LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "SecondsTillShutdown");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 2276),
-UA_NODEID_NUMERIC(ns[0], 2275),
-UA_NODEID_NUMERIC(ns[0], 47),
-UA_QUALIFIEDNAME(ns[0], "ServerViewCount"),
-UA_NODEID_NUMERIC(ns[0], 63),
+UA_NODEID_NUMERIC(ns[0], 2992LU),
+UA_NODEID_NUMERIC(ns[0], 2256LU),
+UA_NODEID_NUMERIC(ns[0], 47LU),
+UA_QUALIFIEDNAME(ns[0], "SecondsTillShutdown"),
+UA_NODEID_NUMERIC(ns[0], 63LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
static UA_StatusCode function_namespace0_generated_147_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2276)
+UA_NODEID_NUMERIC(ns[0], 2992LU)
);
}
-/* CurrentSubscriptionCount - ns=0;i=2285 */
+/* BuildInfo - ns=0;i=2260 */
static UA_StatusCode function_namespace0_generated_148_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
@@ -50126,570 +55768,283 @@ attr.minimumSamplingInterval = 0.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 7);
-attr.displayName = UA_LOCALIZEDTEXT("", "CurrentSubscriptionCount");
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 338LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "BuildInfo");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 2285),
-UA_NODEID_NUMERIC(ns[0], 2275),
-UA_NODEID_NUMERIC(ns[0], 47),
-UA_QUALIFIEDNAME(ns[0], "CurrentSubscriptionCount"),
-UA_NODEID_NUMERIC(ns[0], 63),
+UA_NODEID_NUMERIC(ns[0], 2260LU),
+UA_NODEID_NUMERIC(ns[0], 2256LU),
+UA_NODEID_NUMERIC(ns[0], 47LU),
+UA_QUALIFIEDNAME(ns[0], "BuildInfo"),
+UA_NODEID_NUMERIC(ns[0], 3051LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
static UA_StatusCode function_namespace0_generated_148_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2285)
+UA_NODEID_NUMERIC(ns[0], 2260LU)
);
}
-/* CurrentSessionCount - ns=0;i=2277 */
+/* BuildDate - ns=0;i=2266 */
static UA_StatusCode function_namespace0_generated_149_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_VariableAttributes attr = UA_VariableAttributes_default;
-attr.minimumSamplingInterval = 0.000000;
+attr.minimumSamplingInterval = 1000.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 7);
-attr.displayName = UA_LOCALIZEDTEXT("", "CurrentSessionCount");
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 294LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "BuildDate");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 2277),
-UA_NODEID_NUMERIC(ns[0], 2275),
-UA_NODEID_NUMERIC(ns[0], 47),
-UA_QUALIFIEDNAME(ns[0], "CurrentSessionCount"),
-UA_NODEID_NUMERIC(ns[0], 63),
+UA_NODEID_NUMERIC(ns[0], 2266LU),
+UA_NODEID_NUMERIC(ns[0], 2260LU),
+UA_NODEID_NUMERIC(ns[0], 47LU),
+UA_QUALIFIEDNAME(ns[0], "BuildDate"),
+UA_NODEID_NUMERIC(ns[0], 63LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
static UA_StatusCode function_namespace0_generated_149_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2277)
+UA_NODEID_NUMERIC(ns[0], 2266LU)
);
}
-/* SecurityRejectedSessionCount - ns=0;i=2279 */
+/* BuildNumber - ns=0;i=2265 */
static UA_StatusCode function_namespace0_generated_150_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_VariableAttributes attr = UA_VariableAttributes_default;
-attr.minimumSamplingInterval = 0.000000;
+attr.minimumSamplingInterval = 1000.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 7);
-attr.displayName = UA_LOCALIZEDTEXT("", "SecurityRejectedSessionCount");
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 12LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "BuildNumber");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 2279),
-UA_NODEID_NUMERIC(ns[0], 2275),
-UA_NODEID_NUMERIC(ns[0], 47),
-UA_QUALIFIEDNAME(ns[0], "SecurityRejectedSessionCount"),
-UA_NODEID_NUMERIC(ns[0], 63),
+UA_NODEID_NUMERIC(ns[0], 2265LU),
+UA_NODEID_NUMERIC(ns[0], 2260LU),
+UA_NODEID_NUMERIC(ns[0], 47LU),
+UA_QUALIFIEDNAME(ns[0], "BuildNumber"),
+UA_NODEID_NUMERIC(ns[0], 63LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
static UA_StatusCode function_namespace0_generated_150_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2279)
+UA_NODEID_NUMERIC(ns[0], 2265LU)
);
}
-/* CumulatedSubscriptionCount - ns=0;i=2286 */
+/* SoftwareVersion - ns=0;i=2264 */
static UA_StatusCode function_namespace0_generated_151_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_VariableAttributes attr = UA_VariableAttributes_default;
-attr.minimumSamplingInterval = 0.000000;
+attr.minimumSamplingInterval = 1000.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 7);
-attr.displayName = UA_LOCALIZEDTEXT("", "CumulatedSubscriptionCount");
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 12LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "SoftwareVersion");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 2286),
-UA_NODEID_NUMERIC(ns[0], 2275),
-UA_NODEID_NUMERIC(ns[0], 47),
-UA_QUALIFIEDNAME(ns[0], "CumulatedSubscriptionCount"),
-UA_NODEID_NUMERIC(ns[0], 63),
+UA_NODEID_NUMERIC(ns[0], 2264LU),
+UA_NODEID_NUMERIC(ns[0], 2260LU),
+UA_NODEID_NUMERIC(ns[0], 47LU),
+UA_QUALIFIEDNAME(ns[0], "SoftwareVersion"),
+UA_NODEID_NUMERIC(ns[0], 63LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
static UA_StatusCode function_namespace0_generated_151_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2286)
+UA_NODEID_NUMERIC(ns[0], 2264LU)
);
}
-/* EnabledFlag - ns=0;i=2294 */
+/* ManufacturerName - ns=0;i=2263 */
static UA_StatusCode function_namespace0_generated_152_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_VariableAttributes attr = UA_VariableAttributes_default;
-attr.minimumSamplingInterval = 0.000000;
+attr.minimumSamplingInterval = 1000.000000;
attr.userAccessLevel = 1;
-attr.accessLevel = 3;
+attr.accessLevel = 1;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 1);
-attr.displayName = UA_LOCALIZEDTEXT("", "EnabledFlag");
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 12LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "ManufacturerName");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 2294),
-UA_NODEID_NUMERIC(ns[0], 2274),
-UA_NODEID_NUMERIC(ns[0], 46),
-UA_QUALIFIEDNAME(ns[0], "EnabledFlag"),
-UA_NODEID_NUMERIC(ns[0], 68),
+UA_NODEID_NUMERIC(ns[0], 2263LU),
+UA_NODEID_NUMERIC(ns[0], 2260LU),
+UA_NODEID_NUMERIC(ns[0], 47LU),
+UA_QUALIFIEDNAME(ns[0], "ManufacturerName"),
+UA_NODEID_NUMERIC(ns[0], 63LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
static UA_StatusCode function_namespace0_generated_152_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2294)
+UA_NODEID_NUMERIC(ns[0], 2263LU)
);
}
-/* ServerRedundancy - ns=0;i=2296 */
+/* ProductUri - ns=0;i=2262 */
static UA_StatusCode function_namespace0_generated_153_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
-UA_ObjectAttributes attr = UA_ObjectAttributes_default;
-attr.displayName = UA_LOCALIZEDTEXT("", "ServerRedundancy");
-retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECT,
-UA_NODEID_NUMERIC(ns[0], 2296),
-UA_NODEID_NUMERIC(ns[0], 2253),
-UA_NODEID_NUMERIC(ns[0], 47),
-UA_QUALIFIEDNAME(ns[0], "ServerRedundancy"),
-UA_NODEID_NUMERIC(ns[0], 2034),
-(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
-return retVal;
-}
-
-static UA_StatusCode function_namespace0_generated_153_finish(UA_Server *server, UA_UInt16* ns) {
-return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2296)
-);
-}
-
-/* RedundancySupport - ns=0;i=3709 */
-
-static UA_StatusCode function_namespace0_generated_154_begin(UA_Server *server, UA_UInt16* ns) {
-UA_StatusCode retVal = UA_STATUSCODE_GOOD;
-UA_VariableAttributes attr = UA_VariableAttributes_default;
-attr.minimumSamplingInterval = 0.000000;
-attr.userAccessLevel = 1;
-attr.accessLevel = 1;
-/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 851);
-attr.displayName = UA_LOCALIZEDTEXT("", "RedundancySupport");
-retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 3709),
-UA_NODEID_NUMERIC(ns[0], 2296),
-UA_NODEID_NUMERIC(ns[0], 46),
-UA_QUALIFIEDNAME(ns[0], "RedundancySupport"),
-UA_NODEID_NUMERIC(ns[0], 68),
-(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
-return retVal;
-}
-
-static UA_StatusCode function_namespace0_generated_154_finish(UA_Server *server, UA_UInt16* ns) {
-return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 3709)
-);
-}
-
-/* ServerArray - ns=0;i=2254 */
-
-static UA_StatusCode function_namespace0_generated_155_begin(UA_Server *server, UA_UInt16* ns) {
-UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_VariableAttributes attr = UA_VariableAttributes_default;
attr.minimumSamplingInterval = 1000.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
-attr.valueRank = 1;
-attr.arrayDimensionsSize = 1;
-UA_UInt32 arrayDimensions[1];
-arrayDimensions[0] = 0;
-attr.arrayDimensions = &arrayDimensions[0];
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 12);
-attr.displayName = UA_LOCALIZEDTEXT("", "ServerArray");
-retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 2254),
-UA_NODEID_NUMERIC(ns[0], 2253),
-UA_NODEID_NUMERIC(ns[0], 46),
-UA_QUALIFIEDNAME(ns[0], "ServerArray"),
-UA_NODEID_NUMERIC(ns[0], 68),
-(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
-return retVal;
-}
-
-static UA_StatusCode function_namespace0_generated_155_finish(UA_Server *server, UA_UInt16* ns) {
-return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2254)
-);
-}
-
-/* ServerCapabilities - ns=0;i=2268 */
-
-static UA_StatusCode function_namespace0_generated_156_begin(UA_Server *server, UA_UInt16* ns) {
-UA_StatusCode retVal = UA_STATUSCODE_GOOD;
-UA_ObjectAttributes attr = UA_ObjectAttributes_default;
-attr.displayName = UA_LOCALIZEDTEXT("", "ServerCapabilities");
-retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECT,
-UA_NODEID_NUMERIC(ns[0], 2268),
-UA_NODEID_NUMERIC(ns[0], 2253),
-UA_NODEID_NUMERIC(ns[0], 47),
-UA_QUALIFIEDNAME(ns[0], "ServerCapabilities"),
-UA_NODEID_NUMERIC(ns[0], 2013),
-(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
-return retVal;
-}
-
-static UA_StatusCode function_namespace0_generated_156_finish(UA_Server *server, UA_UInt16* ns) {
-return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2268)
-);
-}
-
-/* MaxBrowseContinuationPoints - ns=0;i=2735 */
-
-static UA_StatusCode function_namespace0_generated_157_begin(UA_Server *server, UA_UInt16* ns) {
-UA_StatusCode retVal = UA_STATUSCODE_GOOD;
-UA_VariableAttributes attr = UA_VariableAttributes_default;
-attr.minimumSamplingInterval = 0.000000;
-attr.userAccessLevel = 1;
-attr.accessLevel = 1;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 5);
-attr.displayName = UA_LOCALIZEDTEXT("", "MaxBrowseContinuationPoints");
-retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 2735),
-UA_NODEID_NUMERIC(ns[0], 2268),
-UA_NODEID_NUMERIC(ns[0], 46),
-UA_QUALIFIEDNAME(ns[0], "MaxBrowseContinuationPoints"),
-UA_NODEID_NUMERIC(ns[0], 68),
-(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
-return retVal;
-}
-
-static UA_StatusCode function_namespace0_generated_157_finish(UA_Server *server, UA_UInt16* ns) {
-return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2735)
-);
-}
-
-/* ModellingRules - ns=0;i=2996 */
-
-static UA_StatusCode function_namespace0_generated_158_begin(UA_Server *server, UA_UInt16* ns) {
-UA_StatusCode retVal = UA_STATUSCODE_GOOD;
-UA_ObjectAttributes attr = UA_ObjectAttributes_default;
-attr.displayName = UA_LOCALIZEDTEXT("", "ModellingRules");
-retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECT,
-UA_NODEID_NUMERIC(ns[0], 2996),
-UA_NODEID_NUMERIC(ns[0], 2268),
-UA_NODEID_NUMERIC(ns[0], 47),
-UA_QUALIFIEDNAME(ns[0], "ModellingRules"),
-UA_NODEID_NUMERIC(ns[0], 61),
-(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
-return retVal;
-}
-
-static UA_StatusCode function_namespace0_generated_158_finish(UA_Server *server, UA_UInt16* ns) {
-return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2996)
-);
-}
-
-/* OperationLimits - ns=0;i=11704 */
-
-static UA_StatusCode function_namespace0_generated_159_begin(UA_Server *server, UA_UInt16* ns) {
-UA_StatusCode retVal = UA_STATUSCODE_GOOD;
-UA_ObjectAttributes attr = UA_ObjectAttributes_default;
-attr.displayName = UA_LOCALIZEDTEXT("", "OperationLimits");
-retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECT,
-UA_NODEID_NUMERIC(ns[0], 11704),
-UA_NODEID_NUMERIC(ns[0], 2268),
-UA_NODEID_NUMERIC(ns[0], 47),
-UA_QUALIFIEDNAME(ns[0], "OperationLimits"),
-UA_NODEID_NUMERIC(ns[0], 11564),
-(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
-return retVal;
-}
-
-static UA_StatusCode function_namespace0_generated_159_finish(UA_Server *server, UA_UInt16* ns) {
-return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 11704)
-);
-}
-
-/* MaxNodesPerNodeManagement - ns=0;i=11713 */
-
-static UA_StatusCode function_namespace0_generated_160_begin(UA_Server *server, UA_UInt16* ns) {
-UA_StatusCode retVal = UA_STATUSCODE_GOOD;
-UA_VariableAttributes attr = UA_VariableAttributes_default;
-attr.minimumSamplingInterval = 0.000000;
-attr.userAccessLevel = 1;
-attr.accessLevel = 1;
-/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 7);
-attr.displayName = UA_LOCALIZEDTEXT("", "MaxNodesPerNodeManagement");
-retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 11713),
-UA_NODEID_NUMERIC(ns[0], 11704),
-UA_NODEID_NUMERIC(ns[0], 46),
-UA_QUALIFIEDNAME(ns[0], "MaxNodesPerNodeManagement"),
-UA_NODEID_NUMERIC(ns[0], 68),
-(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
-return retVal;
-}
-
-static UA_StatusCode function_namespace0_generated_160_finish(UA_Server *server, UA_UInt16* ns) {
-return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 11713)
-);
-}
-
-/* MaxNodesPerWrite - ns=0;i=11707 */
-
-static UA_StatusCode function_namespace0_generated_161_begin(UA_Server *server, UA_UInt16* ns) {
-UA_StatusCode retVal = UA_STATUSCODE_GOOD;
-UA_VariableAttributes attr = UA_VariableAttributes_default;
-attr.minimumSamplingInterval = 0.000000;
-attr.userAccessLevel = 1;
-attr.accessLevel = 1;
-/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 7);
-attr.displayName = UA_LOCALIZEDTEXT("", "MaxNodesPerWrite");
-retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 11707),
-UA_NODEID_NUMERIC(ns[0], 11704),
-UA_NODEID_NUMERIC(ns[0], 46),
-UA_QUALIFIEDNAME(ns[0], "MaxNodesPerWrite"),
-UA_NODEID_NUMERIC(ns[0], 68),
-(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
-return retVal;
-}
-
-static UA_StatusCode function_namespace0_generated_161_finish(UA_Server *server, UA_UInt16* ns) {
-return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 11707)
-);
-}
-
-/* MaxNodesPerRead - ns=0;i=11705 */
-
-static UA_StatusCode function_namespace0_generated_162_begin(UA_Server *server, UA_UInt16* ns) {
-UA_StatusCode retVal = UA_STATUSCODE_GOOD;
-UA_VariableAttributes attr = UA_VariableAttributes_default;
-attr.minimumSamplingInterval = 0.000000;
-attr.userAccessLevel = 1;
-attr.accessLevel = 1;
-/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 7);
-attr.displayName = UA_LOCALIZEDTEXT("", "MaxNodesPerRead");
-retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 11705),
-UA_NODEID_NUMERIC(ns[0], 11704),
-UA_NODEID_NUMERIC(ns[0], 46),
-UA_QUALIFIEDNAME(ns[0], "MaxNodesPerRead"),
-UA_NODEID_NUMERIC(ns[0], 68),
-(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
-return retVal;
-}
-
-static UA_StatusCode function_namespace0_generated_162_finish(UA_Server *server, UA_UInt16* ns) {
-return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 11705)
-);
-}
-
-/* MaxNodesPerBrowse - ns=0;i=11710 */
-
-static UA_StatusCode function_namespace0_generated_163_begin(UA_Server *server, UA_UInt16* ns) {
-UA_StatusCode retVal = UA_STATUSCODE_GOOD;
-UA_VariableAttributes attr = UA_VariableAttributes_default;
-attr.minimumSamplingInterval = 0.000000;
-attr.userAccessLevel = 1;
-attr.accessLevel = 1;
-/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 7);
-attr.displayName = UA_LOCALIZEDTEXT("", "MaxNodesPerBrowse");
-retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 11710),
-UA_NODEID_NUMERIC(ns[0], 11704),
-UA_NODEID_NUMERIC(ns[0], 46),
-UA_QUALIFIEDNAME(ns[0], "MaxNodesPerBrowse"),
-UA_NODEID_NUMERIC(ns[0], 68),
-(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
-return retVal;
-}
-
-static UA_StatusCode function_namespace0_generated_163_finish(UA_Server *server, UA_UInt16* ns) {
-return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 11710)
-);
-}
-
-/* MaxMonitoredItemsPerCall - ns=0;i=11714 */
-
-static UA_StatusCode function_namespace0_generated_164_begin(UA_Server *server, UA_UInt16* ns) {
-UA_StatusCode retVal = UA_STATUSCODE_GOOD;
-UA_VariableAttributes attr = UA_VariableAttributes_default;
-attr.minimumSamplingInterval = 0.000000;
-attr.userAccessLevel = 1;
-attr.accessLevel = 1;
-/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 7);
-attr.displayName = UA_LOCALIZEDTEXT("", "MaxMonitoredItemsPerCall");
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 12LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "ProductUri");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 11714),
-UA_NODEID_NUMERIC(ns[0], 11704),
-UA_NODEID_NUMERIC(ns[0], 46),
-UA_QUALIFIEDNAME(ns[0], "MaxMonitoredItemsPerCall"),
-UA_NODEID_NUMERIC(ns[0], 68),
+UA_NODEID_NUMERIC(ns[0], 2262LU),
+UA_NODEID_NUMERIC(ns[0], 2260LU),
+UA_NODEID_NUMERIC(ns[0], 47LU),
+UA_QUALIFIEDNAME(ns[0], "ProductUri"),
+UA_NODEID_NUMERIC(ns[0], 63LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_164_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_153_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 11714)
+UA_NODEID_NUMERIC(ns[0], 2262LU)
);
}
-/* MaxNodesPerTranslateBrowsePathsToNodeIds - ns=0;i=11712 */
+/* ProductName - ns=0;i=2261 */
-static UA_StatusCode function_namespace0_generated_165_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_154_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_VariableAttributes attr = UA_VariableAttributes_default;
-attr.minimumSamplingInterval = 0.000000;
+attr.minimumSamplingInterval = 1000.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 7);
-attr.displayName = UA_LOCALIZEDTEXT("", "MaxNodesPerTranslateBrowsePathsToNodeIds");
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 12LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "ProductName");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 11712),
-UA_NODEID_NUMERIC(ns[0], 11704),
-UA_NODEID_NUMERIC(ns[0], 46),
-UA_QUALIFIEDNAME(ns[0], "MaxNodesPerTranslateBrowsePathsToNodeIds"),
-UA_NODEID_NUMERIC(ns[0], 68),
+UA_NODEID_NUMERIC(ns[0], 2261LU),
+UA_NODEID_NUMERIC(ns[0], 2260LU),
+UA_NODEID_NUMERIC(ns[0], 47LU),
+UA_QUALIFIEDNAME(ns[0], "ProductName"),
+UA_NODEID_NUMERIC(ns[0], 63LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_165_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_154_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 11712)
+UA_NODEID_NUMERIC(ns[0], 2261LU)
);
}
-/* MaxNodesPerRegisterNodes - ns=0;i=11711 */
+/* State - ns=0;i=2259 */
-static UA_StatusCode function_namespace0_generated_166_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_155_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_VariableAttributes attr = UA_VariableAttributes_default;
attr.minimumSamplingInterval = 0.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 7);
-attr.displayName = UA_LOCALIZEDTEXT("", "MaxNodesPerRegisterNodes");
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 852LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "State");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 11711),
-UA_NODEID_NUMERIC(ns[0], 11704),
-UA_NODEID_NUMERIC(ns[0], 46),
-UA_QUALIFIEDNAME(ns[0], "MaxNodesPerRegisterNodes"),
-UA_NODEID_NUMERIC(ns[0], 68),
+UA_NODEID_NUMERIC(ns[0], 2259LU),
+UA_NODEID_NUMERIC(ns[0], 2256LU),
+UA_NODEID_NUMERIC(ns[0], 47LU),
+UA_QUALIFIEDNAME(ns[0], "State"),
+UA_NODEID_NUMERIC(ns[0], 63LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_166_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_155_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 11711)
+UA_NODEID_NUMERIC(ns[0], 2259LU)
);
}
-/* MaxNodesPerMethodCall - ns=0;i=11709 */
+/* CurrentTime - ns=0;i=2258 */
-static UA_StatusCode function_namespace0_generated_167_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_156_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_VariableAttributes attr = UA_VariableAttributes_default;
attr.minimumSamplingInterval = 0.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 7);
-attr.displayName = UA_LOCALIZEDTEXT("", "MaxNodesPerMethodCall");
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 294LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "CurrentTime");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 11709),
-UA_NODEID_NUMERIC(ns[0], 11704),
-UA_NODEID_NUMERIC(ns[0], 46),
-UA_QUALIFIEDNAME(ns[0], "MaxNodesPerMethodCall"),
-UA_NODEID_NUMERIC(ns[0], 68),
+UA_NODEID_NUMERIC(ns[0], 2258LU),
+UA_NODEID_NUMERIC(ns[0], 2256LU),
+UA_NODEID_NUMERIC(ns[0], 47LU),
+UA_QUALIFIEDNAME(ns[0], "CurrentTime"),
+UA_NODEID_NUMERIC(ns[0], 63LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_167_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_156_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 11709)
+UA_NODEID_NUMERIC(ns[0], 2258LU)
);
}
-/* MaxHistoryContinuationPoints - ns=0;i=2737 */
+/* StartTime - ns=0;i=2257 */
-static UA_StatusCode function_namespace0_generated_168_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_157_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_VariableAttributes attr = UA_VariableAttributes_default;
attr.minimumSamplingInterval = 0.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 5);
-attr.displayName = UA_LOCALIZEDTEXT("", "MaxHistoryContinuationPoints");
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 294LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "StartTime");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 2737),
-UA_NODEID_NUMERIC(ns[0], 2268),
-UA_NODEID_NUMERIC(ns[0], 46),
-UA_QUALIFIEDNAME(ns[0], "MaxHistoryContinuationPoints"),
-UA_NODEID_NUMERIC(ns[0], 68),
+UA_NODEID_NUMERIC(ns[0], 2257LU),
+UA_NODEID_NUMERIC(ns[0], 2256LU),
+UA_NODEID_NUMERIC(ns[0], 47LU),
+UA_QUALIFIEDNAME(ns[0], "StartTime"),
+UA_NODEID_NUMERIC(ns[0], 63LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_168_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_157_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2737)
+UA_NODEID_NUMERIC(ns[0], 2257LU)
);
}
-/* SoftwareCertificates - ns=0;i=3704 */
+/* NamespaceArray - ns=0;i=2255 */
-static UA_StatusCode function_namespace0_generated_169_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_158_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_VariableAttributes attr = UA_VariableAttributes_default;
-attr.minimumSamplingInterval = 0.000000;
+attr.minimumSamplingInterval = 1000.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
attr.valueRank = 1;
@@ -50697,30 +56052,30 @@ attr.arrayDimensionsSize = 1;
UA_UInt32 arrayDimensions[1];
arrayDimensions[0] = 0;
attr.arrayDimensions = &arrayDimensions[0];
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 344);
-attr.displayName = UA_LOCALIZEDTEXT("", "SoftwareCertificates");
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 12LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "NamespaceArray");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 3704),
-UA_NODEID_NUMERIC(ns[0], 2268),
-UA_NODEID_NUMERIC(ns[0], 46),
-UA_QUALIFIEDNAME(ns[0], "SoftwareCertificates"),
-UA_NODEID_NUMERIC(ns[0], 68),
+UA_NODEID_NUMERIC(ns[0], 2255LU),
+UA_NODEID_NUMERIC(ns[0], 2253LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
+UA_QUALIFIEDNAME(ns[0], "NamespaceArray"),
+UA_NODEID_NUMERIC(ns[0], 68LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_169_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_158_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 3704)
+UA_NODEID_NUMERIC(ns[0], 2255LU)
);
}
-/* LocaleIdArray - ns=0;i=2271 */
+/* ServerArray - ns=0;i=2254 */
-static UA_StatusCode function_namespace0_generated_170_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_159_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_VariableAttributes attr = UA_VariableAttributes_default;
-attr.minimumSamplingInterval = 0.000000;
+attr.minimumSamplingInterval = 1000.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
attr.valueRank = 1;
@@ -50728,77 +56083,60 @@ attr.arrayDimensionsSize = 1;
UA_UInt32 arrayDimensions[1];
arrayDimensions[0] = 0;
attr.arrayDimensions = &arrayDimensions[0];
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 295);
-attr.displayName = UA_LOCALIZEDTEXT("", "LocaleIdArray");
-retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 2271),
-UA_NODEID_NUMERIC(ns[0], 2268),
-UA_NODEID_NUMERIC(ns[0], 46),
-UA_QUALIFIEDNAME(ns[0], "LocaleIdArray"),
-UA_NODEID_NUMERIC(ns[0], 68),
-(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
-return retVal;
-}
-
-static UA_StatusCode function_namespace0_generated_170_finish(UA_Server *server, UA_UInt16* ns) {
-return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2271)
-);
-}
-
-/* MaxQueryContinuationPoints - ns=0;i=2736 */
-
-static UA_StatusCode function_namespace0_generated_171_begin(UA_Server *server, UA_UInt16* ns) {
-UA_StatusCode retVal = UA_STATUSCODE_GOOD;
-UA_VariableAttributes attr = UA_VariableAttributes_default;
-attr.minimumSamplingInterval = 0.000000;
-attr.userAccessLevel = 1;
-attr.accessLevel = 1;
-/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 5);
-attr.displayName = UA_LOCALIZEDTEXT("", "MaxQueryContinuationPoints");
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 12LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "ServerArray");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 2736),
-UA_NODEID_NUMERIC(ns[0], 2268),
-UA_NODEID_NUMERIC(ns[0], 46),
-UA_QUALIFIEDNAME(ns[0], "MaxQueryContinuationPoints"),
-UA_NODEID_NUMERIC(ns[0], 68),
+UA_NODEID_NUMERIC(ns[0], 2254LU),
+UA_NODEID_NUMERIC(ns[0], 2253LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
+UA_QUALIFIEDNAME(ns[0], "ServerArray"),
+UA_NODEID_NUMERIC(ns[0], 68LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_171_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_159_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2736)
+UA_NODEID_NUMERIC(ns[0], 2254LU)
);
}
-/* AggregateFunctions - ns=0;i=2997 */
+/* GetMonitoredItems - ns=0;i=11492 */
-static UA_StatusCode function_namespace0_generated_172_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_160_begin(UA_Server *server, UA_UInt16* ns) {
+#ifdef UA_ENABLE_METHODCALLS
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
-UA_ObjectAttributes attr = UA_ObjectAttributes_default;
-attr.displayName = UA_LOCALIZEDTEXT("", "AggregateFunctions");
-retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECT,
-UA_NODEID_NUMERIC(ns[0], 2997),
-UA_NODEID_NUMERIC(ns[0], 2268),
-UA_NODEID_NUMERIC(ns[0], 47),
-UA_QUALIFIEDNAME(ns[0], "AggregateFunctions"),
-UA_NODEID_NUMERIC(ns[0], 61),
-(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
+UA_MethodAttributes attr = UA_MethodAttributes_default;
+attr.executable = true;
+attr.userExecutable = true;
+attr.displayName = UA_LOCALIZEDTEXT("", "GetMonitoredItems");
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_METHOD,
+UA_NODEID_NUMERIC(ns[0], 11492LU),
+UA_NODEID_NUMERIC(ns[0], 2253LU),
+UA_NODEID_NUMERIC(ns[0], 47LU),
+UA_QUALIFIEDNAME(ns[0], "GetMonitoredItems"),
+ UA_NODEID_NULL,
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_METHODATTRIBUTES],NULL, NULL);
return retVal;
+#else
+return UA_STATUSCODE_GOOD;
+#endif /* UA_ENABLE_METHODCALLS */
}
-static UA_StatusCode function_namespace0_generated_172_finish(UA_Server *server, UA_UInt16* ns) {
-return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2997)
-);
+static UA_StatusCode function_namespace0_generated_160_finish(UA_Server *server, UA_UInt16* ns) {
+#ifdef UA_ENABLE_METHODCALLS
+return UA_Server_addMethodNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 11492LU)
+, NULL, 0, NULL, 0, NULL);
+#else
+return UA_STATUSCODE_GOOD;
+#endif /* UA_ENABLE_METHODCALLS */
}
-/* ServerProfileArray - ns=0;i=2269 */
+/* OutputArguments - ns=0;i=11494 */
-static UA_StatusCode function_namespace0_generated_173_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_161_begin(UA_Server *server, UA_UInt16* ns) {
+#ifdef UA_ENABLE_METHODCALLS
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_VariableAttributes attr = UA_VariableAttributes_default;
attr.minimumSamplingInterval = 0.000000;
@@ -50809,952 +56147,726 @@ attr.arrayDimensionsSize = 1;
UA_UInt32 arrayDimensions[1];
arrayDimensions[0] = 0;
attr.arrayDimensions = &arrayDimensions[0];
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 12);
-attr.displayName = UA_LOCALIZEDTEXT("", "ServerProfileArray");
-retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 2269),
-UA_NODEID_NUMERIC(ns[0], 2268),
-UA_NODEID_NUMERIC(ns[0], 46),
-UA_QUALIFIEDNAME(ns[0], "ServerProfileArray"),
-UA_NODEID_NUMERIC(ns[0], 68),
-(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
-return retVal;
-}
-
-static UA_StatusCode function_namespace0_generated_173_finish(UA_Server *server, UA_UInt16* ns) {
-return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2269)
-);
-}
-
-/* HistoryServerCapabilities - ns=0;i=11192 */
-
-static UA_StatusCode function_namespace0_generated_174_begin(UA_Server *server, UA_UInt16* ns) {
-UA_StatusCode retVal = UA_STATUSCODE_GOOD;
-UA_ObjectAttributes attr = UA_ObjectAttributes_default;
-attr.displayName = UA_LOCALIZEDTEXT("", "HistoryServerCapabilities");
-retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECT,
-UA_NODEID_NUMERIC(ns[0], 11192),
-UA_NODEID_NUMERIC(ns[0], 2268),
-UA_NODEID_NUMERIC(ns[0], 47),
-UA_QUALIFIEDNAME(ns[0], "HistoryServerCapabilities"),
-UA_NODEID_NUMERIC(ns[0], 2330),
-(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
-return retVal;
-}
-
-static UA_StatusCode function_namespace0_generated_174_finish(UA_Server *server, UA_UInt16* ns) {
-return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 11192)
-);
-}
-
-/* MaxReturnDataValues - ns=0;i=11273 */
-
-static UA_StatusCode function_namespace0_generated_175_begin(UA_Server *server, UA_UInt16* ns) {
-UA_StatusCode retVal = UA_STATUSCODE_GOOD;
-UA_VariableAttributes attr = UA_VariableAttributes_default;
-attr.minimumSamplingInterval = 0.000000;
-attr.userAccessLevel = 1;
-attr.accessLevel = 1;
-/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 7);
-attr.displayName = UA_LOCALIZEDTEXT("", "MaxReturnDataValues");
-retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 11273),
-UA_NODEID_NUMERIC(ns[0], 11192),
-UA_NODEID_NUMERIC(ns[0], 46),
-UA_QUALIFIEDNAME(ns[0], "MaxReturnDataValues"),
-UA_NODEID_NUMERIC(ns[0], 68),
-(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
-return retVal;
-}
-
-static UA_StatusCode function_namespace0_generated_175_finish(UA_Server *server, UA_UInt16* ns) {
-return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 11273)
-);
-}
-
-/* InsertAnnotationCapability - ns=0;i=11275 */
-
-static UA_StatusCode function_namespace0_generated_176_begin(UA_Server *server, UA_UInt16* ns) {
-UA_StatusCode retVal = UA_STATUSCODE_GOOD;
-UA_VariableAttributes attr = UA_VariableAttributes_default;
-attr.minimumSamplingInterval = 0.000000;
-attr.userAccessLevel = 1;
-attr.accessLevel = 1;
-/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 1);
-attr.displayName = UA_LOCALIZEDTEXT("", "InsertAnnotationCapability");
-retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 11275),
-UA_NODEID_NUMERIC(ns[0], 11192),
-UA_NODEID_NUMERIC(ns[0], 46),
-UA_QUALIFIEDNAME(ns[0], "InsertAnnotationCapability"),
-UA_NODEID_NUMERIC(ns[0], 68),
-(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
-return retVal;
-}
-
-static UA_StatusCode function_namespace0_generated_176_finish(UA_Server *server, UA_UInt16* ns) {
-return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 11275)
-);
-}
-
-/* AggregateFunctions - ns=0;i=11201 */
-
-static UA_StatusCode function_namespace0_generated_177_begin(UA_Server *server, UA_UInt16* ns) {
-UA_StatusCode retVal = UA_STATUSCODE_GOOD;
-UA_ObjectAttributes attr = UA_ObjectAttributes_default;
-attr.displayName = UA_LOCALIZEDTEXT("", "AggregateFunctions");
-retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECT,
-UA_NODEID_NUMERIC(ns[0], 11201),
-UA_NODEID_NUMERIC(ns[0], 11192),
-UA_NODEID_NUMERIC(ns[0], 47),
-UA_QUALIFIEDNAME(ns[0], "AggregateFunctions"),
-UA_NODEID_NUMERIC(ns[0], 61),
-(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
-return retVal;
-}
-
-static UA_StatusCode function_namespace0_generated_177_finish(UA_Server *server, UA_UInt16* ns) {
-return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 11201)
-);
-}
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 296LU);
+UA_Argument variablenode_ns_0_i_11494_variant_DataContents[2];
-/* ReplaceDataCapability - ns=0;i=11197 */
+UA_init(&variablenode_ns_0_i_11494_variant_DataContents[0], &UA_TYPES[UA_TYPES_ARGUMENT]);
+variablenode_ns_0_i_11494_variant_DataContents[0].name = UA_STRING("ServerHandles");
+variablenode_ns_0_i_11494_variant_DataContents[0].dataType = UA_NODEID_NUMERIC(ns[0], 7LU);
+variablenode_ns_0_i_11494_variant_DataContents[0].valueRank = (UA_Int32) 1;
+UA_STACKARRAY(UA_UInt32, variablenode_ns_0_i_11494_variant_DataContents0_arrayDimensions, 1);
+UA_init(variablenode_ns_0_i_11494_variant_DataContents0_arrayDimensions, &UA_TYPES[UA_TYPES_UINT32]);
+variablenode_ns_0_i_11494_variant_DataContents0_arrayDimensions[0] = (UA_UInt32) 0;
+variablenode_ns_0_i_11494_variant_DataContents[0].arrayDimensionsSize = 1;
+variablenode_ns_0_i_11494_variant_DataContents[0].arrayDimensions = variablenode_ns_0_i_11494_variant_DataContents0_arrayDimensions;
-static UA_StatusCode function_namespace0_generated_178_begin(UA_Server *server, UA_UInt16* ns) {
-UA_StatusCode retVal = UA_STATUSCODE_GOOD;
-UA_VariableAttributes attr = UA_VariableAttributes_default;
-attr.minimumSamplingInterval = 0.000000;
-attr.userAccessLevel = 1;
-attr.accessLevel = 1;
-/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 1);
-attr.displayName = UA_LOCALIZEDTEXT("", "ReplaceDataCapability");
+UA_init(&variablenode_ns_0_i_11494_variant_DataContents[1], &UA_TYPES[UA_TYPES_ARGUMENT]);
+variablenode_ns_0_i_11494_variant_DataContents[1].name = UA_STRING("ClientHandles");
+variablenode_ns_0_i_11494_variant_DataContents[1].dataType = UA_NODEID_NUMERIC(ns[0], 7LU);
+variablenode_ns_0_i_11494_variant_DataContents[1].valueRank = (UA_Int32) 1;
+UA_STACKARRAY(UA_UInt32, variablenode_ns_0_i_11494_variant_DataContents1_arrayDimensions, 1);
+UA_init(variablenode_ns_0_i_11494_variant_DataContents1_arrayDimensions, &UA_TYPES[UA_TYPES_UINT32]);
+variablenode_ns_0_i_11494_variant_DataContents1_arrayDimensions[0] = (UA_UInt32) 0;
+variablenode_ns_0_i_11494_variant_DataContents[1].arrayDimensionsSize = 1;
+variablenode_ns_0_i_11494_variant_DataContents[1].arrayDimensions = variablenode_ns_0_i_11494_variant_DataContents1_arrayDimensions;
+UA_Variant_setArray(&attr.value, &variablenode_ns_0_i_11494_variant_DataContents, (UA_Int32) 2, &UA_TYPES[UA_TYPES_ARGUMENT]);
+attr.displayName = UA_LOCALIZEDTEXT("", "OutputArguments");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 11197),
-UA_NODEID_NUMERIC(ns[0], 11192),
-UA_NODEID_NUMERIC(ns[0], 46),
-UA_QUALIFIEDNAME(ns[0], "ReplaceDataCapability"),
-UA_NODEID_NUMERIC(ns[0], 68),
+UA_NODEID_NUMERIC(ns[0], 11494LU),
+UA_NODEID_NUMERIC(ns[0], 11492LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
+UA_QUALIFIEDNAME(ns[0], "OutputArguments"),
+UA_NODEID_NUMERIC(ns[0], 68LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
-return retVal;
-}
-
-static UA_StatusCode function_namespace0_generated_178_finish(UA_Server *server, UA_UInt16* ns) {
-return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 11197)
-);
-}
-/* DeleteRawCapability - ns=0;i=11199 */
-static UA_StatusCode function_namespace0_generated_179_begin(UA_Server *server, UA_UInt16* ns) {
-UA_StatusCode retVal = UA_STATUSCODE_GOOD;
-UA_VariableAttributes attr = UA_VariableAttributes_default;
-attr.minimumSamplingInterval = 0.000000;
-attr.userAccessLevel = 1;
-attr.accessLevel = 1;
-/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 1);
-attr.displayName = UA_LOCALIZEDTEXT("", "DeleteRawCapability");
-retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 11199),
-UA_NODEID_NUMERIC(ns[0], 11192),
-UA_NODEID_NUMERIC(ns[0], 46),
-UA_QUALIFIEDNAME(ns[0], "DeleteRawCapability"),
-UA_NODEID_NUMERIC(ns[0], 68),
-(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
+#else
+return UA_STATUSCODE_GOOD;
+#endif /* UA_ENABLE_METHODCALLS */
}
-static UA_StatusCode function_namespace0_generated_179_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_161_finish(UA_Server *server, UA_UInt16* ns) {
+#ifdef UA_ENABLE_METHODCALLS
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 11199)
+UA_NODEID_NUMERIC(ns[0], 11494LU)
);
+#else
+return UA_STATUSCODE_GOOD;
+#endif /* UA_ENABLE_METHODCALLS */
}
-/* UpdateDataCapability - ns=0;i=11198 */
+/* InputArguments - ns=0;i=11493 */
-static UA_StatusCode function_namespace0_generated_180_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_162_begin(UA_Server *server, UA_UInt16* ns) {
+#ifdef UA_ENABLE_METHODCALLS
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_VariableAttributes attr = UA_VariableAttributes_default;
attr.minimumSamplingInterval = 0.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
-/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 1);
-attr.displayName = UA_LOCALIZEDTEXT("", "UpdateDataCapability");
-retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 11198),
-UA_NODEID_NUMERIC(ns[0], 11192),
-UA_NODEID_NUMERIC(ns[0], 46),
-UA_QUALIFIEDNAME(ns[0], "UpdateDataCapability"),
-UA_NODEID_NUMERIC(ns[0], 68),
-(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
-return retVal;
-}
-
-static UA_StatusCode function_namespace0_generated_180_finish(UA_Server *server, UA_UInt16* ns) {
-return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 11198)
-);
-}
-
-/* InsertDataCapability - ns=0;i=11196 */
+attr.valueRank = 1;
+attr.arrayDimensionsSize = 1;
+UA_UInt32 arrayDimensions[1];
+arrayDimensions[0] = 0;
+attr.arrayDimensions = &arrayDimensions[0];
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 296LU);
+UA_Argument variablenode_ns_0_i_11493_variant_DataContents[1];
-static UA_StatusCode function_namespace0_generated_181_begin(UA_Server *server, UA_UInt16* ns) {
-UA_StatusCode retVal = UA_STATUSCODE_GOOD;
-UA_VariableAttributes attr = UA_VariableAttributes_default;
-attr.minimumSamplingInterval = 0.000000;
-attr.userAccessLevel = 1;
-attr.accessLevel = 1;
-/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 1);
-attr.displayName = UA_LOCALIZEDTEXT("", "InsertDataCapability");
+UA_init(&variablenode_ns_0_i_11493_variant_DataContents[0], &UA_TYPES[UA_TYPES_ARGUMENT]);
+variablenode_ns_0_i_11493_variant_DataContents[0].name = UA_STRING("SubscriptionId");
+variablenode_ns_0_i_11493_variant_DataContents[0].dataType = UA_NODEID_NUMERIC(ns[0], 7LU);
+variablenode_ns_0_i_11493_variant_DataContents[0].valueRank = (UA_Int32) -1;
+UA_Variant_setArray(&attr.value, &variablenode_ns_0_i_11493_variant_DataContents, (UA_Int32) 1, &UA_TYPES[UA_TYPES_ARGUMENT]);
+attr.displayName = UA_LOCALIZEDTEXT("", "InputArguments");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 11196),
-UA_NODEID_NUMERIC(ns[0], 11192),
-UA_NODEID_NUMERIC(ns[0], 46),
-UA_QUALIFIEDNAME(ns[0], "InsertDataCapability"),
-UA_NODEID_NUMERIC(ns[0], 68),
+UA_NODEID_NUMERIC(ns[0], 11493LU),
+UA_NODEID_NUMERIC(ns[0], 11492LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
+UA_QUALIFIEDNAME(ns[0], "InputArguments"),
+UA_NODEID_NUMERIC(ns[0], 68LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
-return retVal;
-}
-
-static UA_StatusCode function_namespace0_generated_181_finish(UA_Server *server, UA_UInt16* ns) {
-return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 11196)
-);
-}
-
-/* ReplaceEventCapability - ns=0;i=11282 */
-static UA_StatusCode function_namespace0_generated_182_begin(UA_Server *server, UA_UInt16* ns) {
-UA_StatusCode retVal = UA_STATUSCODE_GOOD;
-UA_VariableAttributes attr = UA_VariableAttributes_default;
-attr.minimumSamplingInterval = 0.000000;
-attr.userAccessLevel = 1;
-attr.accessLevel = 1;
-/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 1);
-attr.displayName = UA_LOCALIZEDTEXT("", "ReplaceEventCapability");
-retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 11282),
-UA_NODEID_NUMERIC(ns[0], 11192),
-UA_NODEID_NUMERIC(ns[0], 46),
-UA_QUALIFIEDNAME(ns[0], "ReplaceEventCapability"),
-UA_NODEID_NUMERIC(ns[0], 68),
-(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
return retVal;
+#else
+return UA_STATUSCODE_GOOD;
+#endif /* UA_ENABLE_METHODCALLS */
}
-static UA_StatusCode function_namespace0_generated_182_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_162_finish(UA_Server *server, UA_UInt16* ns) {
+#ifdef UA_ENABLE_METHODCALLS
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 11282)
+UA_NODEID_NUMERIC(ns[0], 11493LU)
);
+#else
+return UA_STATUSCODE_GOOD;
+#endif /* UA_ENABLE_METHODCALLS */
}
-/* AccessHistoryEventsCapability - ns=0;i=11242 */
+/* VendorServerInfo - ns=0;i=2011 */
-static UA_StatusCode function_namespace0_generated_183_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_163_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
-UA_VariableAttributes attr = UA_VariableAttributes_default;
-attr.minimumSamplingInterval = 0.000000;
-attr.userAccessLevel = 1;
-attr.accessLevel = 1;
-/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 1);
-attr.displayName = UA_LOCALIZEDTEXT("", "AccessHistoryEventsCapability");
-retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 11242),
-UA_NODEID_NUMERIC(ns[0], 11192),
-UA_NODEID_NUMERIC(ns[0], 46),
-UA_QUALIFIEDNAME(ns[0], "AccessHistoryEventsCapability"),
-UA_NODEID_NUMERIC(ns[0], 68),
-(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+UA_ObjectAttributes attr = UA_ObjectAttributes_default;
+attr.displayName = UA_LOCALIZEDTEXT("", "VendorServerInfo");
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECT,
+UA_NODEID_NUMERIC(ns[0], 2011LU),
+UA_NODEID_NUMERIC(ns[0], 2004LU),
+UA_NODEID_NUMERIC(ns[0], 47LU),
+UA_QUALIFIEDNAME(ns[0], "VendorServerInfo"),
+UA_NODEID_NUMERIC(ns[0], 2033LU),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_183_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_163_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 11242)
+UA_NODEID_NUMERIC(ns[0], 2011LU)
);
}
-/* MaxReturnEventValues - ns=0;i=11274 */
+/* ModellingRuleType - ns=0;i=77 */
-static UA_StatusCode function_namespace0_generated_184_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_164_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
-UA_VariableAttributes attr = UA_VariableAttributes_default;
-attr.minimumSamplingInterval = 0.000000;
-attr.userAccessLevel = 1;
-attr.accessLevel = 1;
-/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 7);
-attr.displayName = UA_LOCALIZEDTEXT("", "MaxReturnEventValues");
-retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 11274),
-UA_NODEID_NUMERIC(ns[0], 11192),
-UA_NODEID_NUMERIC(ns[0], 46),
-UA_QUALIFIEDNAME(ns[0], "MaxReturnEventValues"),
-UA_NODEID_NUMERIC(ns[0], 68),
-(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default;
+attr.displayName = UA_LOCALIZEDTEXT("", "ModellingRuleType");
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECTTYPE,
+UA_NODEID_NUMERIC(ns[0], 77LU),
+UA_NODEID_NUMERIC(ns[0], 58LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
+UA_QUALIFIEDNAME(ns[0], "ModellingRuleType"),
+ UA_NODEID_NULL,
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_184_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_164_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 11274)
+UA_NODEID_NUMERIC(ns[0], 77LU)
);
}
-/* AccessHistoryDataCapability - ns=0;i=11193 */
+/* ExposesItsArray - ns=0;i=83 */
-static UA_StatusCode function_namespace0_generated_185_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_165_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
-UA_VariableAttributes attr = UA_VariableAttributes_default;
-attr.minimumSamplingInterval = 0.000000;
-attr.userAccessLevel = 1;
-attr.accessLevel = 1;
-/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 1);
-attr.displayName = UA_LOCALIZEDTEXT("", "AccessHistoryDataCapability");
-retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 11193),
-UA_NODEID_NUMERIC(ns[0], 11192),
-UA_NODEID_NUMERIC(ns[0], 46),
-UA_QUALIFIEDNAME(ns[0], "AccessHistoryDataCapability"),
-UA_NODEID_NUMERIC(ns[0], 68),
-(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+UA_ObjectAttributes attr = UA_ObjectAttributes_default;
+attr.displayName = UA_LOCALIZEDTEXT("", "ExposesItsArray");
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECT,
+UA_NODEID_NUMERIC(ns[0], 83LU),
+UA_NODEID_NUMERIC(ns[0], 0LU),
+UA_NODEID_NUMERIC(ns[0], 0LU),
+UA_QUALIFIEDNAME(ns[0], "ExposesItsArray"),
+UA_NODEID_NUMERIC(ns[0], 77LU),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_185_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_165_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 11193)
+UA_NODEID_NUMERIC(ns[0], 83LU)
);
}
-/* DeleteEventCapability - ns=0;i=11502 */
+/* NamingRule - ns=0;i=114 */
-static UA_StatusCode function_namespace0_generated_186_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_166_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_VariableAttributes attr = UA_VariableAttributes_default;
attr.minimumSamplingInterval = 0.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 1);
-attr.displayName = UA_LOCALIZEDTEXT("", "DeleteEventCapability");
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 120LU);
+UA_Int32 *variablenode_ns_0_i_114_variant_DataContents = UA_Int32_new();
+if (!variablenode_ns_0_i_114_variant_DataContents) return UA_STATUSCODE_BADOUTOFMEMORY;
+UA_Int32_init(variablenode_ns_0_i_114_variant_DataContents);
+*variablenode_ns_0_i_114_variant_DataContents = (UA_Int32) 3;
+UA_Variant_setScalar(&attr.value, variablenode_ns_0_i_114_variant_DataContents, &UA_TYPES[UA_TYPES_INT32]);
+attr.displayName = UA_LOCALIZEDTEXT("", "NamingRule");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 11502),
-UA_NODEID_NUMERIC(ns[0], 11192),
-UA_NODEID_NUMERIC(ns[0], 46),
-UA_QUALIFIEDNAME(ns[0], "DeleteEventCapability"),
-UA_NODEID_NUMERIC(ns[0], 68),
+UA_NODEID_NUMERIC(ns[0], 114LU),
+UA_NODEID_NUMERIC(ns[0], 83LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
+UA_QUALIFIEDNAME(ns[0], "NamingRule"),
+UA_NODEID_NUMERIC(ns[0], 68LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+UA_Int32_delete(variablenode_ns_0_i_114_variant_DataContents);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_186_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_166_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 11502)
+UA_NODEID_NUMERIC(ns[0], 114LU)
);
}
-/* InsertEventCapability - ns=0;i=11281 */
+/* Optional - ns=0;i=80 */
-static UA_StatusCode function_namespace0_generated_187_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_167_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
-UA_VariableAttributes attr = UA_VariableAttributes_default;
-attr.minimumSamplingInterval = 0.000000;
-attr.userAccessLevel = 1;
-attr.accessLevel = 1;
-/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 1);
-attr.displayName = UA_LOCALIZEDTEXT("", "InsertEventCapability");
-retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 11281),
-UA_NODEID_NUMERIC(ns[0], 11192),
-UA_NODEID_NUMERIC(ns[0], 46),
-UA_QUALIFIEDNAME(ns[0], "InsertEventCapability"),
-UA_NODEID_NUMERIC(ns[0], 68),
-(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+UA_ObjectAttributes attr = UA_ObjectAttributes_default;
+attr.displayName = UA_LOCALIZEDTEXT("", "Optional");
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECT,
+UA_NODEID_NUMERIC(ns[0], 80LU),
+UA_NODEID_NUMERIC(ns[0], 0LU),
+UA_NODEID_NUMERIC(ns[0], 0LU),
+UA_QUALIFIEDNAME(ns[0], "Optional"),
+UA_NODEID_NUMERIC(ns[0], 77LU),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 80LU), UA_NODEID_NUMERIC(ns[0], 37LU), UA_EXPANDEDNODEID_NUMERIC(ns[0], 11570LU), false);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 80LU), UA_NODEID_NUMERIC(ns[0], 37LU), UA_EXPANDEDNODEID_NUMERIC(ns[0], 11574LU), false);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 80LU), UA_NODEID_NUMERIC(ns[0], 37LU), UA_EXPANDEDNODEID_NUMERIC(ns[0], 11573LU), false);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 80LU), UA_NODEID_NUMERIC(ns[0], 37LU), UA_EXPANDEDNODEID_NUMERIC(ns[0], 11551LU), false);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 80LU), UA_NODEID_NUMERIC(ns[0], 37LU), UA_EXPANDEDNODEID_NUMERIC(ns[0], 11572LU), false);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 80LU), UA_NODEID_NUMERIC(ns[0], 37LU), UA_EXPANDEDNODEID_NUMERIC(ns[0], 11569LU), false);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 80LU), UA_NODEID_NUMERIC(ns[0], 37LU), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2366LU), false);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 80LU), UA_NODEID_NUMERIC(ns[0], 37LU), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2371LU), false);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 80LU), UA_NODEID_NUMERIC(ns[0], 37LU), UA_EXPANDEDNODEID_NUMERIC(ns[0], 11571LU), false);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 80LU), UA_NODEID_NUMERIC(ns[0], 37LU), UA_EXPANDEDNODEID_NUMERIC(ns[0], 11567LU), false);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 80LU), UA_NODEID_NUMERIC(ns[0], 37LU), UA_EXPANDEDNODEID_NUMERIC(ns[0], 11565LU), false);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 80LU), UA_NODEID_NUMERIC(ns[0], 37LU), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2367LU), false);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 80LU), UA_NODEID_NUMERIC(ns[0], 37LU), UA_EXPANDEDNODEID_NUMERIC(ns[0], 3190LU), false);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 80LU), UA_NODEID_NUMERIC(ns[0], 37LU), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2370LU), false);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_187_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_167_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 11281)
+UA_NODEID_NUMERIC(ns[0], 80LU)
);
}
-/* DeleteAtTimeCapability - ns=0;i=11200 */
+/* NamingRule - ns=0;i=113 */
-static UA_StatusCode function_namespace0_generated_188_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_168_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_VariableAttributes attr = UA_VariableAttributes_default;
attr.minimumSamplingInterval = 0.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 1);
-attr.displayName = UA_LOCALIZEDTEXT("", "DeleteAtTimeCapability");
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 120LU);
+UA_Int32 *variablenode_ns_0_i_113_variant_DataContents = UA_Int32_new();
+if (!variablenode_ns_0_i_113_variant_DataContents) return UA_STATUSCODE_BADOUTOFMEMORY;
+UA_Int32_init(variablenode_ns_0_i_113_variant_DataContents);
+*variablenode_ns_0_i_113_variant_DataContents = (UA_Int32) 2;
+UA_Variant_setScalar(&attr.value, variablenode_ns_0_i_113_variant_DataContents, &UA_TYPES[UA_TYPES_INT32]);
+attr.displayName = UA_LOCALIZEDTEXT("", "NamingRule");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 11200),
-UA_NODEID_NUMERIC(ns[0], 11192),
-UA_NODEID_NUMERIC(ns[0], 46),
-UA_QUALIFIEDNAME(ns[0], "DeleteAtTimeCapability"),
-UA_NODEID_NUMERIC(ns[0], 68),
+UA_NODEID_NUMERIC(ns[0], 113LU),
+UA_NODEID_NUMERIC(ns[0], 80LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
+UA_QUALIFIEDNAME(ns[0], "NamingRule"),
+UA_NODEID_NUMERIC(ns[0], 68LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+UA_Int32_delete(variablenode_ns_0_i_113_variant_DataContents);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_188_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_168_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 11200)
+UA_NODEID_NUMERIC(ns[0], 113LU)
);
}
-/* UpdateEventCapability - ns=0;i=11283 */
+/* Mandatory - ns=0;i=78 */
-static UA_StatusCode function_namespace0_generated_189_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_169_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
-UA_VariableAttributes attr = UA_VariableAttributes_default;
-attr.minimumSamplingInterval = 0.000000;
-attr.userAccessLevel = 1;
-attr.accessLevel = 1;
-/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 1);
-attr.displayName = UA_LOCALIZEDTEXT("", "UpdateEventCapability");
-retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 11283),
-UA_NODEID_NUMERIC(ns[0], 11192),
-UA_NODEID_NUMERIC(ns[0], 46),
-UA_QUALIFIEDNAME(ns[0], "UpdateEventCapability"),
-UA_NODEID_NUMERIC(ns[0], 68),
-(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+UA_ObjectAttributes attr = UA_ObjectAttributes_default;
+attr.displayName = UA_LOCALIZEDTEXT("", "Mandatory");
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECT,
+UA_NODEID_NUMERIC(ns[0], 78LU),
+UA_NODEID_NUMERIC(ns[0], 0LU),
+UA_NODEID_NUMERIC(ns[0], 0LU),
+UA_QUALIFIEDNAME(ns[0], "Mandatory"),
+UA_NODEID_NUMERIC(ns[0], 77LU),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 78LU), UA_NODEID_NUMERIC(ns[0], 37LU), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2374LU), false);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 78LU), UA_NODEID_NUMERIC(ns[0], 37LU), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2369LU), false);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 78LU), UA_NODEID_NUMERIC(ns[0], 37LU), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2050LU), false);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 78LU), UA_NODEID_NUMERIC(ns[0], 37LU), UA_EXPANDEDNODEID_NUMERIC(ns[0], 12169LU), false);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 78LU), UA_NODEID_NUMERIC(ns[0], 37LU), UA_EXPANDEDNODEID_NUMERIC(ns[0], 7611LU), false);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 78LU), UA_NODEID_NUMERIC(ns[0], 37LU), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2042LU), false);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 78LU), UA_NODEID_NUMERIC(ns[0], 37LU), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2046LU), false);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 78LU), UA_NODEID_NUMERIC(ns[0], 37LU), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2375LU), false);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 78LU), UA_NODEID_NUMERIC(ns[0], 37LU), UA_EXPANDEDNODEID_NUMERIC(ns[0], 12078LU), false);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 78LU), UA_NODEID_NUMERIC(ns[0], 37LU), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2035LU), false);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 78LU), UA_NODEID_NUMERIC(ns[0], 37LU), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2051LU), false);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 78LU), UA_NODEID_NUMERIC(ns[0], 37LU), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2045LU), false);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 78LU), UA_NODEID_NUMERIC(ns[0], 37LU), UA_EXPANDEDNODEID_NUMERIC(ns[0], 11241LU), false);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 78LU), UA_NODEID_NUMERIC(ns[0], 37LU), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2011LU), false);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 78LU), UA_NODEID_NUMERIC(ns[0], 37LU), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2377LU), false);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 78LU), UA_NODEID_NUMERIC(ns[0], 37LU), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2047LU), false);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 78LU), UA_NODEID_NUMERIC(ns[0], 37LU), UA_EXPANDEDNODEID_NUMERIC(ns[0], 11461LU), false);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 78LU), UA_NODEID_NUMERIC(ns[0], 37LU), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2044LU), false);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 78LU), UA_NODEID_NUMERIC(ns[0], 37LU), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2043LU), false);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_189_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_169_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 11283)
+UA_NODEID_NUMERIC(ns[0], 78LU)
);
}
-/* MinSupportedSampleRate - ns=0;i=2272 */
+/* NamingRule - ns=0;i=112 */
-static UA_StatusCode function_namespace0_generated_190_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_170_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_VariableAttributes attr = UA_VariableAttributes_default;
attr.minimumSamplingInterval = 0.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 290);
-attr.displayName = UA_LOCALIZEDTEXT("", "MinSupportedSampleRate");
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 120LU);
+UA_Int32 *variablenode_ns_0_i_112_variant_DataContents = UA_Int32_new();
+if (!variablenode_ns_0_i_112_variant_DataContents) return UA_STATUSCODE_BADOUTOFMEMORY;
+UA_Int32_init(variablenode_ns_0_i_112_variant_DataContents);
+*variablenode_ns_0_i_112_variant_DataContents = (UA_Int32) 1;
+UA_Variant_setScalar(&attr.value, variablenode_ns_0_i_112_variant_DataContents, &UA_TYPES[UA_TYPES_INT32]);
+attr.displayName = UA_LOCALIZEDTEXT("", "NamingRule");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 2272),
-UA_NODEID_NUMERIC(ns[0], 2268),
-UA_NODEID_NUMERIC(ns[0], 46),
-UA_QUALIFIEDNAME(ns[0], "MinSupportedSampleRate"),
-UA_NODEID_NUMERIC(ns[0], 68),
+UA_NODEID_NUMERIC(ns[0], 112LU),
+UA_NODEID_NUMERIC(ns[0], 78LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
+UA_QUALIFIEDNAME(ns[0], "NamingRule"),
+UA_NODEID_NUMERIC(ns[0], 68LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+UA_Int32_delete(variablenode_ns_0_i_112_variant_DataContents);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_190_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_170_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2272)
+UA_NODEID_NUMERIC(ns[0], 112LU)
);
}
-/* VendorServerInfo - ns=0;i=2011 */
+/* MandatoryPlaceholder - ns=0;i=11510 */
-static UA_StatusCode function_namespace0_generated_191_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_171_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_ObjectAttributes attr = UA_ObjectAttributes_default;
-attr.displayName = UA_LOCALIZEDTEXT("", "VendorServerInfo");
+attr.displayName = UA_LOCALIZEDTEXT("", "MandatoryPlaceholder");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECT,
-UA_NODEID_NUMERIC(ns[0], 2011),
-UA_NODEID_NUMERIC(ns[0], 2004),
-UA_NODEID_NUMERIC(ns[0], 47),
-UA_QUALIFIEDNAME(ns[0], "VendorServerInfo"),
-UA_NODEID_NUMERIC(ns[0], 2033),
+UA_NODEID_NUMERIC(ns[0], 11510LU),
+UA_NODEID_NUMERIC(ns[0], 0LU),
+UA_NODEID_NUMERIC(ns[0], 0LU),
+UA_QUALIFIEDNAME(ns[0], "MandatoryPlaceholder"),
+UA_NODEID_NUMERIC(ns[0], 77LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_191_finish(UA_Server *server, UA_UInt16* ns) {
-return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 2011)
-);
-}
-
-/* ModellingRuleType - ns=0;i=77 */
-
-static UA_StatusCode function_namespace0_generated_192_begin(UA_Server *server, UA_UInt16* ns) {
-UA_StatusCode retVal = UA_STATUSCODE_GOOD;
-UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default;
-attr.displayName = UA_LOCALIZEDTEXT("", "ModellingRuleType");
-retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECTTYPE,
-UA_NODEID_NUMERIC(ns[0], 77),
-UA_NODEID_NUMERIC(ns[0], 58),
-UA_NODEID_NUMERIC(ns[0], 45),
-UA_QUALIFIEDNAME(ns[0], "ModellingRuleType"),
- UA_NODEID_NULL,
-(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL);
-return retVal;
-}
-
-static UA_StatusCode function_namespace0_generated_192_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_171_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 77)
+UA_NODEID_NUMERIC(ns[0], 11510LU)
);
}
-/* NamingRule - ns=0;i=111 */
+/* NamingRule - ns=0;i=11511 */
-static UA_StatusCode function_namespace0_generated_193_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_172_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_VariableAttributes attr = UA_VariableAttributes_default;
attr.minimumSamplingInterval = 0.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 120);
-UA_Int32 *variablenode_ns_0_i_111_variant_DataContents = UA_Int32_new();
-if (!variablenode_ns_0_i_111_variant_DataContents) return UA_STATUSCODE_BADOUTOFMEMORY;
-UA_Int32_init(variablenode_ns_0_i_111_variant_DataContents);
-*variablenode_ns_0_i_111_variant_DataContents = (UA_Int32) 1;
-UA_Variant_setScalar(&attr.value, variablenode_ns_0_i_111_variant_DataContents, &UA_TYPES[UA_TYPES_INT32]);
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 120LU);
+UA_Int32 *variablenode_ns_0_i_11511_variant_DataContents = UA_Int32_new();
+if (!variablenode_ns_0_i_11511_variant_DataContents) return UA_STATUSCODE_BADOUTOFMEMORY;
+UA_Int32_init(variablenode_ns_0_i_11511_variant_DataContents);
+*variablenode_ns_0_i_11511_variant_DataContents = (UA_Int32) 1;
+UA_Variant_setScalar(&attr.value, variablenode_ns_0_i_11511_variant_DataContents, &UA_TYPES[UA_TYPES_INT32]);
attr.displayName = UA_LOCALIZEDTEXT("", "NamingRule");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 111),
-UA_NODEID_NUMERIC(ns[0], 77),
-UA_NODEID_NUMERIC(ns[0], 46),
+UA_NODEID_NUMERIC(ns[0], 11511LU),
+UA_NODEID_NUMERIC(ns[0], 11510LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
UA_QUALIFIEDNAME(ns[0], "NamingRule"),
-UA_NODEID_NUMERIC(ns[0], 68),
+UA_NODEID_NUMERIC(ns[0], 68LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
-UA_Int32_delete(variablenode_ns_0_i_111_variant_DataContents);
+UA_Int32_delete(variablenode_ns_0_i_11511_variant_DataContents);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_193_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_172_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 111)
+UA_NODEID_NUMERIC(ns[0], 11511LU)
);
}
-/* Optional - ns=0;i=80 */
+/* OptionalPlaceholder - ns=0;i=11508 */
-static UA_StatusCode function_namespace0_generated_194_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_173_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_ObjectAttributes attr = UA_ObjectAttributes_default;
-attr.displayName = UA_LOCALIZEDTEXT("", "Optional");
+attr.displayName = UA_LOCALIZEDTEXT("", "OptionalPlaceholder");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECT,
-UA_NODEID_NUMERIC(ns[0], 80),
-UA_NODEID_NUMERIC(ns[0], 0),
-UA_NODEID_NUMERIC(ns[0], 0),
-UA_QUALIFIEDNAME(ns[0], "Optional"),
-UA_NODEID_NUMERIC(ns[0], 77),
+UA_NODEID_NUMERIC(ns[0], 11508LU),
+UA_NODEID_NUMERIC(ns[0], 0LU),
+UA_NODEID_NUMERIC(ns[0], 0LU),
+UA_QUALIFIEDNAME(ns[0], "OptionalPlaceholder"),
+UA_NODEID_NUMERIC(ns[0], 77LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
-retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 80), UA_NODEID_NUMERIC(ns[0], 37), UA_EXPANDEDNODEID_NUMERIC(ns[0], 11571), false);
-retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 80), UA_NODEID_NUMERIC(ns[0], 37), UA_EXPANDEDNODEID_NUMERIC(ns[0], 11574), false);
-retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 80), UA_NODEID_NUMERIC(ns[0], 37), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2366), false);
-retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 80), UA_NODEID_NUMERIC(ns[0], 37), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2371), false);
-retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 80), UA_NODEID_NUMERIC(ns[0], 37), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2370), false);
-retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 80), UA_NODEID_NUMERIC(ns[0], 37), UA_EXPANDEDNODEID_NUMERIC(ns[0], 11569), false);
-retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 80), UA_NODEID_NUMERIC(ns[0], 37), UA_EXPANDEDNODEID_NUMERIC(ns[0], 3190), false);
-retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 80), UA_NODEID_NUMERIC(ns[0], 37), UA_EXPANDEDNODEID_NUMERIC(ns[0], 11565), false);
-retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 80), UA_NODEID_NUMERIC(ns[0], 37), UA_EXPANDEDNODEID_NUMERIC(ns[0], 11567), false);
-retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 80), UA_NODEID_NUMERIC(ns[0], 37), UA_EXPANDEDNODEID_NUMERIC(ns[0], 11570), false);
-retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 80), UA_NODEID_NUMERIC(ns[0], 37), UA_EXPANDEDNODEID_NUMERIC(ns[0], 11573), false);
-retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 80), UA_NODEID_NUMERIC(ns[0], 37), UA_EXPANDEDNODEID_NUMERIC(ns[0], 11551), false);
-retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 80), UA_NODEID_NUMERIC(ns[0], 37), UA_EXPANDEDNODEID_NUMERIC(ns[0], 11572), false);
-retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 80), UA_NODEID_NUMERIC(ns[0], 37), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2367), false);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_194_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_173_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 80)
+UA_NODEID_NUMERIC(ns[0], 11508LU)
);
}
-/* NamingRule - ns=0;i=113 */
+/* NamingRule - ns=0;i=11509 */
-static UA_StatusCode function_namespace0_generated_195_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_174_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_VariableAttributes attr = UA_VariableAttributes_default;
attr.minimumSamplingInterval = 0.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 120);
-UA_Int32 *variablenode_ns_0_i_113_variant_DataContents = UA_Int32_new();
-if (!variablenode_ns_0_i_113_variant_DataContents) return UA_STATUSCODE_BADOUTOFMEMORY;
-UA_Int32_init(variablenode_ns_0_i_113_variant_DataContents);
-*variablenode_ns_0_i_113_variant_DataContents = (UA_Int32) 2;
-UA_Variant_setScalar(&attr.value, variablenode_ns_0_i_113_variant_DataContents, &UA_TYPES[UA_TYPES_INT32]);
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 120LU);
+UA_Int32 *variablenode_ns_0_i_11509_variant_DataContents = UA_Int32_new();
+if (!variablenode_ns_0_i_11509_variant_DataContents) return UA_STATUSCODE_BADOUTOFMEMORY;
+UA_Int32_init(variablenode_ns_0_i_11509_variant_DataContents);
+*variablenode_ns_0_i_11509_variant_DataContents = (UA_Int32) 2;
+UA_Variant_setScalar(&attr.value, variablenode_ns_0_i_11509_variant_DataContents, &UA_TYPES[UA_TYPES_INT32]);
attr.displayName = UA_LOCALIZEDTEXT("", "NamingRule");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 113),
-UA_NODEID_NUMERIC(ns[0], 80),
-UA_NODEID_NUMERIC(ns[0], 46),
+UA_NODEID_NUMERIC(ns[0], 11509LU),
+UA_NODEID_NUMERIC(ns[0], 11508LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
UA_QUALIFIEDNAME(ns[0], "NamingRule"),
-UA_NODEID_NUMERIC(ns[0], 68),
+UA_NODEID_NUMERIC(ns[0], 68LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
-UA_Int32_delete(variablenode_ns_0_i_113_variant_DataContents);
+UA_Int32_delete(variablenode_ns_0_i_11509_variant_DataContents);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_195_finish(UA_Server *server, UA_UInt16* ns) {
-return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 113)
-);
-}
-
-/* Mandatory - ns=0;i=78 */
-
-static UA_StatusCode function_namespace0_generated_196_begin(UA_Server *server, UA_UInt16* ns) {
-UA_StatusCode retVal = UA_STATUSCODE_GOOD;
-UA_ObjectAttributes attr = UA_ObjectAttributes_default;
-attr.displayName = UA_LOCALIZEDTEXT("", "Mandatory");
-retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECT,
-UA_NODEID_NUMERIC(ns[0], 78),
-UA_NODEID_NUMERIC(ns[0], 0),
-UA_NODEID_NUMERIC(ns[0], 0),
-UA_QUALIFIEDNAME(ns[0], "Mandatory"),
-UA_NODEID_NUMERIC(ns[0], 77),
-(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
-retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 78), UA_NODEID_NUMERIC(ns[0], 37), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2152), false);
-retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 78), UA_NODEID_NUMERIC(ns[0], 37), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2011), false);
-retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 78), UA_NODEID_NUMERIC(ns[0], 37), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2151), false);
-retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 78), UA_NODEID_NUMERIC(ns[0], 37), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2051), false);
-retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 78), UA_NODEID_NUMERIC(ns[0], 37), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2157), false);
-retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 78), UA_NODEID_NUMERIC(ns[0], 37), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2047), false);
-retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 78), UA_NODEID_NUMERIC(ns[0], 37), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2045), false);
-retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 78), UA_NODEID_NUMERIC(ns[0], 37), UA_EXPANDEDNODEID_NUMERIC(ns[0], 111), false);
-retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 78), UA_NODEID_NUMERIC(ns[0], 37), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2043), false);
-retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 78), UA_NODEID_NUMERIC(ns[0], 37), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2035), false);
-retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 78), UA_NODEID_NUMERIC(ns[0], 37), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2160), false);
-retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 78), UA_NODEID_NUMERIC(ns[0], 37), UA_EXPANDEDNODEID_NUMERIC(ns[0], 11241), false);
-retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 78), UA_NODEID_NUMERIC(ns[0], 37), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2159), false);
-retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 78), UA_NODEID_NUMERIC(ns[0], 37), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2162), false);
-retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 78), UA_NODEID_NUMERIC(ns[0], 37), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2154), false);
-retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 78), UA_NODEID_NUMERIC(ns[0], 37), UA_EXPANDEDNODEID_NUMERIC(ns[0], 11461), false);
-retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 78), UA_NODEID_NUMERIC(ns[0], 37), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2155), false);
-retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 78), UA_NODEID_NUMERIC(ns[0], 37), UA_EXPANDEDNODEID_NUMERIC(ns[0], 12169), false);
-retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 78), UA_NODEID_NUMERIC(ns[0], 37), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2163), false);
-retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 78), UA_NODEID_NUMERIC(ns[0], 37), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2369), false);
-retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 78), UA_NODEID_NUMERIC(ns[0], 37), UA_EXPANDEDNODEID_NUMERIC(ns[0], 7611), false);
-retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 78), UA_NODEID_NUMERIC(ns[0], 37), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2046), false);
-retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 78), UA_NODEID_NUMERIC(ns[0], 37), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2374), false);
-retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 78), UA_NODEID_NUMERIC(ns[0], 37), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2377), false);
-retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 78), UA_NODEID_NUMERIC(ns[0], 37), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2044), false);
-retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 78), UA_NODEID_NUMERIC(ns[0], 37), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2050), false);
-retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 78), UA_NODEID_NUMERIC(ns[0], 37), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2375), false);
-retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 78), UA_NODEID_NUMERIC(ns[0], 37), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2153), false);
-retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 78), UA_NODEID_NUMERIC(ns[0], 37), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2161), false);
-retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 78), UA_NODEID_NUMERIC(ns[0], 37), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2156), false);
-retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 78), UA_NODEID_NUMERIC(ns[0], 37), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2042), false);
-retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 78), UA_NODEID_NUMERIC(ns[0], 37), UA_EXPANDEDNODEID_NUMERIC(ns[0], 12078), false);
-return retVal;
-}
-
-static UA_StatusCode function_namespace0_generated_196_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_174_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 78)
+UA_NODEID_NUMERIC(ns[0], 11509LU)
);
}
-/* NamingRule - ns=0;i=112 */
+/* NamingRule - ns=0;i=111 */
-static UA_StatusCode function_namespace0_generated_197_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_175_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_VariableAttributes attr = UA_VariableAttributes_default;
attr.minimumSamplingInterval = 0.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 120);
-UA_Int32 *variablenode_ns_0_i_112_variant_DataContents = UA_Int32_new();
-if (!variablenode_ns_0_i_112_variant_DataContents) return UA_STATUSCODE_BADOUTOFMEMORY;
-UA_Int32_init(variablenode_ns_0_i_112_variant_DataContents);
-*variablenode_ns_0_i_112_variant_DataContents = (UA_Int32) 1;
-UA_Variant_setScalar(&attr.value, variablenode_ns_0_i_112_variant_DataContents, &UA_TYPES[UA_TYPES_INT32]);
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 120LU);
+UA_Int32 *variablenode_ns_0_i_111_variant_DataContents = UA_Int32_new();
+if (!variablenode_ns_0_i_111_variant_DataContents) return UA_STATUSCODE_BADOUTOFMEMORY;
+UA_Int32_init(variablenode_ns_0_i_111_variant_DataContents);
+*variablenode_ns_0_i_111_variant_DataContents = (UA_Int32) 1;
+UA_Variant_setScalar(&attr.value, variablenode_ns_0_i_111_variant_DataContents, &UA_TYPES[UA_TYPES_INT32]);
attr.displayName = UA_LOCALIZEDTEXT("", "NamingRule");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 112),
-UA_NODEID_NUMERIC(ns[0], 78),
-UA_NODEID_NUMERIC(ns[0], 46),
+UA_NODEID_NUMERIC(ns[0], 111LU),
+UA_NODEID_NUMERIC(ns[0], 77LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
UA_QUALIFIEDNAME(ns[0], "NamingRule"),
-UA_NODEID_NUMERIC(ns[0], 68),
+UA_NODEID_NUMERIC(ns[0], 68LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
-UA_Int32_delete(variablenode_ns_0_i_112_variant_DataContents);
+UA_Int32_delete(variablenode_ns_0_i_111_variant_DataContents);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 111LU), UA_NODEID_NUMERIC(ns[0], 37LU), UA_EXPANDEDNODEID_NUMERIC(ns[0], 78LU), true);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_197_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_175_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 112)
+UA_NODEID_NUMERIC(ns[0], 111LU)
);
}
/* DataTypeEncodingType - ns=0;i=76 */
-static UA_StatusCode function_namespace0_generated_198_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_176_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default;
attr.displayName = UA_LOCALIZEDTEXT("", "DataTypeEncodingType");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECTTYPE,
-UA_NODEID_NUMERIC(ns[0], 76),
-UA_NODEID_NUMERIC(ns[0], 58),
-UA_NODEID_NUMERIC(ns[0], 45),
+UA_NODEID_NUMERIC(ns[0], 76LU),
+UA_NODEID_NUMERIC(ns[0], 58LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
UA_QUALIFIEDNAME(ns[0], "DataTypeEncodingType"),
UA_NODEID_NULL,
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_198_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_176_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 76)
+UA_NODEID_NUMERIC(ns[0], 76LU)
);
}
-/* Default JSON - ns=0;i=15375 */
+/* Default Binary - ns=0;i=8251 */
-static UA_StatusCode function_namespace0_generated_199_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_177_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_ObjectAttributes attr = UA_ObjectAttributes_default;
-attr.displayName = UA_LOCALIZEDTEXT("", "Default JSON");
+attr.displayName = UA_LOCALIZEDTEXT("", "Default Binary");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECT,
-UA_NODEID_NUMERIC(ns[0], 15375),
-UA_NODEID_NUMERIC(ns[0], 0),
-UA_NODEID_NUMERIC(ns[0], 0),
-UA_QUALIFIEDNAME(ns[0], "Default JSON"),
-UA_NODEID_NUMERIC(ns[0], 76),
+UA_NODEID_NUMERIC(ns[0], 8251LU),
+UA_NODEID_NUMERIC(ns[0], 0LU),
+UA_NODEID_NUMERIC(ns[0], 0LU),
+UA_QUALIFIEDNAME(ns[0], "Default Binary"),
+UA_NODEID_NUMERIC(ns[0], 76LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
-retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 15375), UA_NODEID_NUMERIC(ns[0], 38), UA_EXPANDEDNODEID_NUMERIC(ns[0], 884), false);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 8251LU), UA_NODEID_NUMERIC(ns[0], 38LU), UA_EXPANDEDNODEID_NUMERIC(ns[0], 7594LU), false);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_199_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_177_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 15375)
+UA_NODEID_NUMERIC(ns[0], 8251LU)
);
}
-/* Default Binary - ns=0;i=8251 */
+/* Default Binary - ns=0;i=298 */
-static UA_StatusCode function_namespace0_generated_200_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_178_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_ObjectAttributes attr = UA_ObjectAttributes_default;
attr.displayName = UA_LOCALIZEDTEXT("", "Default Binary");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECT,
-UA_NODEID_NUMERIC(ns[0], 8251),
-UA_NODEID_NUMERIC(ns[0], 0),
-UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 298LU),
+UA_NODEID_NUMERIC(ns[0], 0LU),
+UA_NODEID_NUMERIC(ns[0], 0LU),
UA_QUALIFIEDNAME(ns[0], "Default Binary"),
-UA_NODEID_NUMERIC(ns[0], 76),
+UA_NODEID_NUMERIC(ns[0], 76LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
-retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 8251), UA_NODEID_NUMERIC(ns[0], 38), UA_EXPANDEDNODEID_NUMERIC(ns[0], 7594), false);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 298LU), UA_NODEID_NUMERIC(ns[0], 38LU), UA_EXPANDEDNODEID_NUMERIC(ns[0], 296LU), false);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_200_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_178_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 8251)
+UA_NODEID_NUMERIC(ns[0], 298LU)
);
}
-/* Default Binary - ns=0;i=298 */
+/* Default JSON - ns=0;i=15376 */
-static UA_StatusCode function_namespace0_generated_201_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_179_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_ObjectAttributes attr = UA_ObjectAttributes_default;
-attr.displayName = UA_LOCALIZEDTEXT("", "Default Binary");
+attr.displayName = UA_LOCALIZEDTEXT("", "Default JSON");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECT,
-UA_NODEID_NUMERIC(ns[0], 298),
-UA_NODEID_NUMERIC(ns[0], 0),
-UA_NODEID_NUMERIC(ns[0], 0),
-UA_QUALIFIEDNAME(ns[0], "Default Binary"),
-UA_NODEID_NUMERIC(ns[0], 76),
+UA_NODEID_NUMERIC(ns[0], 15376LU),
+UA_NODEID_NUMERIC(ns[0], 0LU),
+UA_NODEID_NUMERIC(ns[0], 0LU),
+UA_QUALIFIEDNAME(ns[0], "Default JSON"),
+UA_NODEID_NUMERIC(ns[0], 76LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
-retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 298), UA_NODEID_NUMERIC(ns[0], 38), UA_EXPANDEDNODEID_NUMERIC(ns[0], 296), false);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 15376LU), UA_NODEID_NUMERIC(ns[0], 38LU), UA_EXPANDEDNODEID_NUMERIC(ns[0], 887LU), false);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_201_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_179_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 298)
+UA_NODEID_NUMERIC(ns[0], 15376LU)
);
}
-/* Default JSON - ns=0;i=15376 */
+/* Default JSON - ns=0;i=15375 */
-static UA_StatusCode function_namespace0_generated_202_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_180_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_ObjectAttributes attr = UA_ObjectAttributes_default;
attr.displayName = UA_LOCALIZEDTEXT("", "Default JSON");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECT,
-UA_NODEID_NUMERIC(ns[0], 15376),
-UA_NODEID_NUMERIC(ns[0], 0),
-UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 15375LU),
+UA_NODEID_NUMERIC(ns[0], 0LU),
+UA_NODEID_NUMERIC(ns[0], 0LU),
UA_QUALIFIEDNAME(ns[0], "Default JSON"),
-UA_NODEID_NUMERIC(ns[0], 76),
+UA_NODEID_NUMERIC(ns[0], 76LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
-retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 15376), UA_NODEID_NUMERIC(ns[0], 38), UA_EXPANDEDNODEID_NUMERIC(ns[0], 887), false);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 15375LU), UA_NODEID_NUMERIC(ns[0], 38LU), UA_EXPANDEDNODEID_NUMERIC(ns[0], 884LU), false);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_202_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_180_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 15376)
+UA_NODEID_NUMERIC(ns[0], 15375LU)
);
}
/* DataTypeSystemType - ns=0;i=75 */
-static UA_StatusCode function_namespace0_generated_203_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_181_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default;
attr.displayName = UA_LOCALIZEDTEXT("", "DataTypeSystemType");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECTTYPE,
-UA_NODEID_NUMERIC(ns[0], 75),
-UA_NODEID_NUMERIC(ns[0], 58),
-UA_NODEID_NUMERIC(ns[0], 45),
+UA_NODEID_NUMERIC(ns[0], 75LU),
+UA_NODEID_NUMERIC(ns[0], 58LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
UA_QUALIFIEDNAME(ns[0], "DataTypeSystemType"),
UA_NODEID_NULL,
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_203_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_181_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 75)
+UA_NODEID_NUMERIC(ns[0], 75LU)
);
}
-/* XML Schema - ns=0;i=92 */
+/* OPC Binary - ns=0;i=93 */
-static UA_StatusCode function_namespace0_generated_204_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_182_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_ObjectAttributes attr = UA_ObjectAttributes_default;
-attr.displayName = UA_LOCALIZEDTEXT("", "XML Schema");
+attr.displayName = UA_LOCALIZEDTEXT("", "OPC Binary");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECT,
-UA_NODEID_NUMERIC(ns[0], 92),
-UA_NODEID_NUMERIC(ns[0], 90),
-UA_NODEID_NUMERIC(ns[0], 35),
-UA_QUALIFIEDNAME(ns[0], "XML Schema"),
-UA_NODEID_NUMERIC(ns[0], 75),
+UA_NODEID_NUMERIC(ns[0], 93LU),
+UA_NODEID_NUMERIC(ns[0], 90LU),
+UA_NODEID_NUMERIC(ns[0], 35LU),
+UA_QUALIFIEDNAME(ns[0], "OPC Binary"),
+UA_NODEID_NUMERIC(ns[0], 75LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_204_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_182_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 92)
+UA_NODEID_NUMERIC(ns[0], 93LU)
);
}
-/* OPC Binary - ns=0;i=93 */
+/* XML Schema - ns=0;i=92 */
-static UA_StatusCode function_namespace0_generated_205_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_183_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_ObjectAttributes attr = UA_ObjectAttributes_default;
-attr.displayName = UA_LOCALIZEDTEXT("", "OPC Binary");
+attr.displayName = UA_LOCALIZEDTEXT("", "XML Schema");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECT,
-UA_NODEID_NUMERIC(ns[0], 93),
-UA_NODEID_NUMERIC(ns[0], 90),
-UA_NODEID_NUMERIC(ns[0], 35),
-UA_QUALIFIEDNAME(ns[0], "OPC Binary"),
-UA_NODEID_NUMERIC(ns[0], 75),
+UA_NODEID_NUMERIC(ns[0], 92LU),
+UA_NODEID_NUMERIC(ns[0], 90LU),
+UA_NODEID_NUMERIC(ns[0], 35LU),
+UA_QUALIFIEDNAME(ns[0], "XML Schema"),
+UA_NODEID_NUMERIC(ns[0], 75LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_205_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_183_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 93)
+UA_NODEID_NUMERIC(ns[0], 92LU)
);
}
/* DataTypeDictionaryType - ns=0;i=72 */
-static UA_StatusCode function_namespace0_generated_206_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_184_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_VariableTypeAttributes attr = UA_VariableTypeAttributes_default;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 15);
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 15LU);
attr.displayName = UA_LOCALIZEDTEXT("", "DataTypeDictionaryType");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLETYPE,
-UA_NODEID_NUMERIC(ns[0], 72),
-UA_NODEID_NUMERIC(ns[0], 63),
-UA_NODEID_NUMERIC(ns[0], 45),
+UA_NODEID_NUMERIC(ns[0], 72LU),
+UA_NODEID_NUMERIC(ns[0], 63LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
UA_QUALIFIEDNAME(ns[0], "DataTypeDictionaryType"),
-UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_206_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_184_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 72)
+UA_NODEID_NUMERIC(ns[0], 72LU)
);
}
/* Opc.Ua - ns=0;i=7617 */
+static const UA_Byte variablenode_ns_0_i_7617_variant_DataContents_byteArray[177218] = {60, 111, 112, 99, 58, 84, 121, 112, 101, 68, 105, 99, 116, 105, 111, 110, 97, 114, 121, 13, 10, 32, 32, 120, 109, 108, 110, 115, 58, 111, 112, 99, 61, 34, 104, 116, 116, 112, 58, 47, 47, 111, 112, 99, 102, 111, 117, 110, 100, 97, 116, 105, 111, 110, 46, 111, 114, 103, 47, 66, 105, 110, 97, 114, 121, 83, 99, 104, 101, 109, 97, 47, 34, 13, 10, 32, 32, 120, 109, 108, 110, 115, 58, 120, 115, 105, 61, 34, 104, 116, 116, 112, 58, 47, 47, 119, 119, 119, 46, 119, 51, 46, 111, 114, 103, 47, 50, 48, 48, 49, 47, 88, 77, 76, 83, 99, 104, 101, 109, 97, 45, 105, 110, 115, 116, 97, 110, 99, 101, 34, 13, 10, 32, 32, 120, 109, 108, 110, 115, 58, 117, 97, 61, 34, 104, 116, 116, 112, 58, 47, 47, 111, 112, 99, 102, 111, 117, 110, 100, 97, 116, 105, 111, 110, 46, 111, 114, 103, 47, 85, 65, 47, 34, 13, 10, 32, 32, 120, 109, 108, 110, 115, 58, 116, 110, 115, 61, 34, 104, 116, 116, 112, 58, 47, 47, 111, 112, 99, 102, 111, 117, 110, 100, 97, 116, 105, 111, 110, 46, 111, 114, 103, 47, 85, 65, 47, 34, 13, 10, 32, 32, 68, 101, 102, 97, 117, 108, 116, 66, 121, 116, 101, 79, 114, 100, 101, 114, 61, 34, 76, 105, 116, 116, 108, 101, 69, 110, 100, 105, 97, 110, 34, 13, 10, 32, 32, 84, 97, 114, 103, 101, 116, 78, 97, 109, 101, 115, 112, 97, 99, 101, 61, 34, 104, 116, 116, 112, 58, 47, 47, 111, 112, 99, 102, 111, 117, 110, 100, 97, 116, 105, 111, 110, 46, 111, 114, 103, 47, 85, 65, 47, 34, 13, 10, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 73, 109, 112, 111, 114, 116, 32, 78, 97, 109, 101, 115, 112, 97, 99, 101, 61, 34, 104, 116, 116, 112, 58, 47, 47, 111, 112, 99, 102, 111, 117, 110, 100, 97, 116, 105, 111, 110, 46, 111, 114, 103, 47, 66, 105, 110, 97, 114, 121, 83, 99, 104, 101, 109, 97, 47, 34, 32, 47, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 88, 109, 108, 69, 108, 101, 109, 101, 110, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 68, 111, 99, 117, 109, 101, 110, 116, 97, 116, 105, 111, 110, 62, 65, 110, 32, 88, 77, 76, 32, 101, 108, 101, 109, 101, 110, 116, 32, 101, 110, 99, 111, 100, 101, 100, 32, 97, 115, 32, 97, 32, 85, 84, 70, 45, 56, 32, 115, 116, 114, 105, 110, 103, 46, 60, 47, 111, 112, 99, 58, 68, 111, 99, 117, 109, 101, 110, 116, 97, 116, 105, 111, 110, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 76, 101, 110, 103, 116, 104, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 86, 97, 108, 117, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 67, 104, 97, 114, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 76, 101, 110, 103, 116, 104, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 73, 100, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 54, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 68, 111, 99, 117, 109, 101, 110, 116, 97, 116, 105, 111, 110, 62, 84, 104, 101, 32, 112, 111, 115, 115, 105, 98, 108, 101, 32, 101, 110, 99, 111, 100, 105, 110, 103, 115, 32, 102, 111, 114, 32, 97, 32, 78, 111, 100, 101, 73, 100, 32, 118, 97, 108, 117, 101, 46, 60, 47, 111, 112, 99, 58, 68, 111, 99, 117, 109, 101, 110, 116, 97, 116, 105, 111, 110, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 84, 119, 111, 66, 121, 116, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 70, 111, 117, 114, 66, 121, 116, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 117, 109, 101, 114, 105, 99, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 83, 116, 114, 105, 110, 103, 34, 32, 86, 97, 108, 117, 101, 61, 34, 51, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 71, 117, 105, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 86, 97, 108, 117, 101, 61, 34, 53, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 84, 119, 111, 66, 121, 116, 101, 78, 111, 100, 101, 73, 100, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 100, 101, 110, 116, 105, 102, 105, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 70, 111, 117, 114, 66, 121, 116, 101, 78, 111, 100, 101, 73, 100, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 101, 115, 112, 97, 99, 101, 73, 110, 100, 101, 120, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 100, 101, 110, 116, 105, 102, 105, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 78, 117, 109, 101, 114, 105, 99, 78, 111, 100, 101, 73, 100, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 101, 115, 112, 97, 99, 101, 73, 110, 100, 101, 120, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 100, 101, 110, 116, 105, 102, 105, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 116, 114, 105, 110, 103, 78, 111, 100, 101, 73, 100, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 101, 115, 112, 97, 99, 101, 73, 110, 100, 101, 120, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 100, 101, 110, 116, 105, 102, 105, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 67, 104, 97, 114, 65, 114, 114, 97, 121, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 71, 117, 105, 100, 78, 111, 100, 101, 73, 100, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 101, 115, 112, 97, 99, 101, 73, 110, 100, 101, 120, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 100, 101, 110, 116, 105, 102, 105, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 71, 117, 105, 100, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 78, 111, 100, 101, 73, 100, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 101, 115, 112, 97, 99, 101, 73, 110, 100, 101, 120, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 100, 101, 110, 116, 105, 102, 105, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 73, 100, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 68, 111, 99, 117, 109, 101, 110, 116, 97, 116, 105, 111, 110, 62, 65, 110, 32, 105, 100, 101, 110, 116, 105, 102, 105, 101, 114, 32, 102, 111, 114, 32, 97, 32, 110, 111, 100, 101, 32, 105, 110, 32, 97, 32, 85, 65, 32, 115, 101, 114, 118, 101, 114, 32, 97, 100, 100, 114, 101, 115, 115, 32, 115, 112, 97, 99, 101, 46, 60, 47, 111, 112, 99, 58, 68, 111, 99, 117, 109, 101, 110, 116, 97, 116, 105, 111, 110, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 73, 100, 84, 121, 112, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 101, 114, 118, 101, 100, 49, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 105, 116, 34, 32, 76, 101, 110, 103, 116, 104, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 119, 111, 66, 121, 116, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 84, 119, 111, 66, 121, 116, 101, 78, 111, 100, 101, 73, 100, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 100, 101, 73, 100, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 70, 111, 117, 114, 66, 121, 116, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 70, 111, 117, 114, 66, 121, 116, 101, 78, 111, 100, 101, 73, 100, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 100, 101, 73, 100, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 117, 109, 101, 114, 105, 99, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 117, 109, 101, 114, 105, 99, 78, 111, 100, 101, 73, 100, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 100, 101, 73, 100, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 116, 114, 105, 110, 103, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 114, 105, 110, 103, 78, 111, 100, 101, 73, 100, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 100, 101, 73, 100, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 51, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 71, 117, 105, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 71, 117, 105, 100, 78, 111, 100, 101, 73, 100, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 100, 101, 73, 100, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 78, 111, 100, 101, 73, 100, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 100, 101, 73, 100, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 53, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 69, 120, 112, 97, 110, 100, 101, 100, 78, 111, 100, 101, 73, 100, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 68, 111, 99, 117, 109, 101, 110, 116, 97, 116, 105, 111, 110, 62, 65, 110, 32, 105, 100, 101, 110, 116, 105, 102, 105, 101, 114, 32, 102, 111, 114, 32, 97, 32, 110, 111, 100, 101, 32, 105, 110, 32, 97, 32, 85, 65, 32, 115, 101, 114, 118, 101, 114, 32, 97, 100, 100, 114, 101, 115, 115, 32, 115, 112, 97, 99, 101, 32, 113, 117, 97, 108, 105, 102, 105, 101, 100, 32, 119, 105, 116, 104, 32, 97, 32, 99, 111, 109, 112, 108, 101, 116, 101, 32, 110, 97, 109, 101, 115, 112, 97, 99, 101, 32, 115, 116, 114, 105, 110, 103, 46, 60, 47, 111, 112, 99, 58, 68, 111, 99, 117, 109, 101, 110, 116, 97, 116, 105, 111, 110, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 73, 100, 84, 121, 112, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 73, 110, 100, 101, 120, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 105, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 101, 115, 112, 97, 99, 101, 85, 82, 73, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 105, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 119, 111, 66, 121, 116, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 84, 119, 111, 66, 121, 116, 101, 78, 111, 100, 101, 73, 100, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 100, 101, 73, 100, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 70, 111, 117, 114, 66, 121, 116, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 70, 111, 117, 114, 66, 121, 116, 101, 78, 111, 100, 101, 73, 100, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 100, 101, 73, 100, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 117, 109, 101, 114, 105, 99, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 117, 109, 101, 114, 105, 99, 78, 111, 100, 101, 73, 100, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 100, 101, 73, 100, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 116, 114, 105, 110, 103, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 114, 105, 110, 103, 78, 111, 100, 101, 73, 100, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 100, 101, 73, 100, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 51, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 71, 117, 105, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 71, 117, 105, 100, 78, 111, 100, 101, 73, 100, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 100, 101, 73, 100, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 78, 111, 100, 101, 73, 100, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 100, 101, 73, 100, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 53, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 101, 115, 112, 97, 99, 101, 85, 82, 73, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 67, 104, 97, 114, 65, 114, 114, 97, 121, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 78, 97, 109, 101, 115, 112, 97, 99, 101, 85, 82, 73, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 73, 110, 100, 101, 120, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 83, 101, 114, 118, 101, 114, 73, 110, 100, 101, 120, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 32, 66, 121, 116, 101, 79, 114, 100, 101, 114, 83, 105, 103, 110, 105, 102, 105, 99, 97, 110, 116, 61, 34, 116, 114, 117, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 68, 111, 99, 117, 109, 101, 110, 116, 97, 116, 105, 111, 110, 62, 65, 32, 51, 50, 45, 98, 105, 116, 32, 115, 116, 97, 116, 117, 115, 32, 99, 111, 100, 101, 32, 118, 97, 108, 117, 101, 46, 60, 47, 111, 112, 99, 58, 68, 111, 99, 117, 109, 101, 110, 116, 97, 116, 105, 111, 110, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 68, 111, 99, 117, 109, 101, 110, 116, 97, 116, 105, 111, 110, 62, 65, 32, 114, 101, 99, 117, 114, 115, 105, 118, 101, 32, 115, 116, 114, 117, 99, 116, 117, 114, 101, 32, 99, 111, 110, 116, 97, 105, 110, 105, 110, 103, 32, 100, 105, 97, 103, 110, 111, 115, 116, 105, 99, 32, 105, 110, 102, 111, 114, 109, 97, 116, 105, 111, 110, 32, 97, 115, 115, 111, 99, 105, 97, 116, 101, 100, 32, 119, 105, 116, 104, 32, 97, 32, 115, 116, 97, 116, 117, 115, 32, 99, 111, 100, 101, 46, 60, 47, 111, 112, 99, 58, 68, 111, 99, 117, 109, 101, 110, 116, 97, 116, 105, 111, 110, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 121, 109, 98, 111, 108, 105, 99, 73, 100, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 105, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 101, 115, 112, 97, 99, 101, 85, 82, 73, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 105, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 105, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 76, 111, 99, 97, 108, 101, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 105, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 100, 100, 105, 116, 105, 111, 110, 97, 108, 73, 110, 102, 111, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 105, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 110, 110, 101, 114, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 105, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 110, 110, 101, 114, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 105, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 101, 114, 118, 101, 100, 49, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 105, 116, 34, 32, 76, 101, 110, 103, 116, 104, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 121, 109, 98, 111, 108, 105, 99, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 83, 121, 109, 98, 111, 108, 105, 99, 73, 100, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 101, 115, 112, 97, 99, 101, 85, 82, 73, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 78, 97, 109, 101, 115, 112, 97, 99, 101, 85, 82, 73, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 76, 111, 99, 97, 108, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 76, 111, 99, 97, 108, 101, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 100, 100, 105, 116, 105, 111, 110, 97, 108, 73, 110, 102, 111, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 67, 104, 97, 114, 65, 114, 114, 97, 121, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 65, 100, 100, 105, 116, 105, 111, 110, 97, 108, 73, 110, 102, 111, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 110, 110, 101, 114, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 73, 110, 110, 101, 114, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 110, 110, 101, 114, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 73, 110, 110, 101, 114, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 81, 117, 97, 108, 105, 102, 105, 101, 100, 78, 97, 109, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 68, 111, 99, 117, 109, 101, 110, 116, 97, 116, 105, 111, 110, 62, 65, 32, 115, 116, 114, 105, 110, 103, 32, 113, 117, 97, 108, 105, 102, 105, 101, 100, 32, 119, 105, 116, 104, 32, 97, 32, 110, 97, 109, 101, 115, 112, 97, 99, 101, 32, 105, 110, 100, 101, 120, 46, 60, 47, 111, 112, 99, 58, 68, 111, 99, 117, 109, 101, 110, 116, 97, 116, 105, 111, 110, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 101, 115, 112, 97, 99, 101, 73, 110, 100, 101, 120, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 67, 104, 97, 114, 65, 114, 114, 97, 121, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 68, 111, 99, 117, 109, 101, 110, 116, 97, 116, 105, 111, 110, 62, 65, 32, 115, 116, 114, 105, 110, 103, 32, 113, 117, 97, 108, 105, 102, 105, 101, 100, 32, 119, 105, 116, 104, 32, 97, 32, 110, 97, 109, 101, 115, 112, 97, 99, 101, 32, 105, 110, 100, 101, 120, 46, 60, 47, 111, 112, 99, 58, 68, 111, 99, 117, 109, 101, 110, 116, 97, 116, 105, 111, 110, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 76, 111, 99, 97, 108, 101, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 105, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 101, 120, 116, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 105, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 101, 114, 118, 101, 100, 49, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 105, 116, 34, 32, 76, 101, 110, 103, 116, 104, 61, 34, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 76, 111, 99, 97, 108, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 67, 104, 97, 114, 65, 114, 114, 97, 121, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 76, 111, 99, 97, 108, 101, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 101, 120, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 67, 104, 97, 114, 65, 114, 114, 97, 121, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 84, 101, 120, 116, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 86, 97, 108, 117, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 68, 111, 99, 117, 109, 101, 110, 116, 97, 116, 105, 111, 110, 62, 65, 32, 118, 97, 108, 117, 101, 32, 119, 105, 116, 104, 32, 97, 110, 32, 97, 115, 115, 111, 99, 105, 97, 116, 101, 100, 32, 116, 105, 109, 101, 115, 116, 97, 109, 112, 44, 32, 97, 110, 100, 32, 113, 117, 97, 108, 105, 116, 121, 46, 60, 47, 111, 112, 99, 58, 68, 111, 99, 117, 109, 101, 110, 116, 97, 116, 105, 111, 110, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 86, 97, 108, 117, 101, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 105, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 105, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 111, 117, 114, 99, 101, 84, 105, 109, 101, 115, 116, 97, 109, 112, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 105, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 84, 105, 109, 101, 115, 116, 97, 109, 112, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 105, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 111, 117, 114, 99, 101, 80, 105, 99, 111, 115, 101, 99, 111, 110, 100, 115, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 105, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 80, 105, 99, 111, 115, 101, 99, 111, 110, 100, 115, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 105, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 101, 114, 118, 101, 100, 49, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 105, 116, 34, 32, 76, 101, 110, 103, 116, 104, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 86, 97, 108, 117, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 86, 97, 114, 105, 97, 110, 116, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 86, 97, 108, 117, 101, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 111, 117, 114, 99, 101, 84, 105, 109, 101, 115, 116, 97, 109, 112, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 83, 111, 117, 114, 99, 101, 84, 105, 109, 101, 115, 116, 97, 109, 112, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 111, 117, 114, 99, 101, 80, 105, 99, 111, 115, 101, 99, 111, 110, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 49, 54, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 83, 111, 117, 114, 99, 101, 80, 105, 99, 111, 115, 101, 99, 111, 110, 100, 115, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 84, 105, 109, 101, 115, 116, 97, 109, 112, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 83, 101, 114, 118, 101, 114, 84, 105, 109, 101, 115, 116, 97, 109, 112, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 80, 105, 99, 111, 115, 101, 99, 111, 110, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 49, 54, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 83, 101, 114, 118, 101, 114, 80, 105, 99, 111, 115, 101, 99, 111, 110, 100, 115, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 68, 111, 99, 117, 109, 101, 110, 116, 97, 116, 105, 111, 110, 62, 65, 32, 115, 101, 114, 105, 97, 108, 105, 122, 101, 100, 32, 111, 98, 106, 101, 99, 116, 32, 112, 114, 101, 102, 105, 120, 101, 100, 32, 119, 105, 116, 104, 32, 105, 116, 115, 32, 100, 97, 116, 97, 32, 116, 121, 112, 101, 32, 105, 100, 101, 110, 116, 105, 102, 105, 101, 114, 46, 60, 47, 111, 112, 99, 58, 68, 111, 99, 117, 109, 101, 110, 116, 97, 116, 105, 111, 110, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 121, 112, 101, 73, 100, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 105, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 105, 110, 97, 114, 121, 66, 111, 100, 121, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 105, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 88, 109, 108, 66, 111, 100, 121, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 105, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 101, 114, 118, 101, 100, 49, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 105, 116, 34, 32, 76, 101, 110, 103, 116, 104, 61, 34, 53, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 121, 112, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 112, 97, 110, 100, 101, 100, 78, 111, 100, 101, 73, 100, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 84, 121, 112, 101, 73, 100, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 111, 100, 121, 76, 101, 110, 103, 116, 104, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 111, 100, 121, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 66, 111, 100, 121, 76, 101, 110, 103, 116, 104, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 86, 97, 114, 105, 97, 110, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 68, 111, 99, 117, 109, 101, 110, 116, 97, 116, 105, 111, 110, 62, 65, 32, 117, 110, 105, 111, 110, 32, 111, 102, 32, 115, 101, 118, 101, 114, 97, 108, 32, 116, 121, 112, 101, 115, 46, 60, 47, 111, 112, 99, 58, 68, 111, 99, 117, 109, 101, 110, 116, 97, 116, 105, 111, 110, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 86, 97, 114, 105, 97, 110, 116, 84, 121, 112, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 105, 116, 34, 32, 76, 101, 110, 103, 116, 104, 61, 34, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 114, 114, 97, 121, 68, 105, 109, 101, 110, 115, 105, 111, 110, 115, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 105, 116, 34, 32, 76, 101, 110, 103, 116, 104, 61, 34, 49, 34, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 114, 114, 97, 121, 76, 101, 110, 103, 116, 104, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 105, 116, 34, 32, 76, 101, 110, 103, 116, 104, 61, 34, 49, 34, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 114, 114, 97, 121, 76, 101, 110, 103, 116, 104, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 65, 114, 114, 97, 121, 76, 101, 110, 103, 116, 104, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 111, 111, 108, 101, 97, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 65, 114, 114, 97, 121, 76, 101, 110, 103, 116, 104, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 86, 97, 114, 105, 97, 110, 116, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 66, 121, 116, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 66, 121, 116, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 65, 114, 114, 97, 121, 76, 101, 110, 103, 116, 104, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 86, 97, 114, 105, 97, 110, 116, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 121, 116, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 65, 114, 114, 97, 121, 76, 101, 110, 103, 116, 104, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 86, 97, 114, 105, 97, 110, 116, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 51, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 110, 116, 49, 54, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 49, 54, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 65, 114, 114, 97, 121, 76, 101, 110, 103, 116, 104, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 86, 97, 114, 105, 97, 110, 116, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 73, 110, 116, 49, 54, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 49, 54, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 65, 114, 114, 97, 121, 76, 101, 110, 103, 116, 104, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 86, 97, 114, 105, 97, 110, 116, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 53, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 110, 116, 51, 50, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 65, 114, 114, 97, 121, 76, 101, 110, 103, 116, 104, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 86, 97, 114, 105, 97, 110, 116, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 73, 110, 116, 51, 50, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 65, 114, 114, 97, 121, 76, 101, 110, 103, 116, 104, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 86, 97, 114, 105, 97, 110, 116, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 55, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 110, 116, 54, 52, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 54, 52, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 65, 114, 114, 97, 121, 76, 101, 110, 103, 116, 104, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 86, 97, 114, 105, 97, 110, 116, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 56, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 73, 110, 116, 54, 52, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 54, 52, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 65, 114, 114, 97, 121, 76, 101, 110, 103, 116, 104, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 86, 97, 114, 105, 97, 110, 116, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 57, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 70, 108, 111, 97, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 70, 108, 111, 97, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 65, 114, 114, 97, 121, 76, 101, 110, 103, 116, 104, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 86, 97, 114, 105, 97, 110, 116, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 49, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 111, 117, 98, 108, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 65, 114, 114, 97, 121, 76, 101, 110, 103, 116, 104, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 86, 97, 114, 105, 97, 110, 116, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 49, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 116, 114, 105, 110, 103, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 67, 104, 97, 114, 65, 114, 114, 97, 121, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 65, 114, 114, 97, 121, 76, 101, 110, 103, 116, 104, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 86, 97, 114, 105, 97, 110, 116, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 49, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 65, 114, 114, 97, 121, 76, 101, 110, 103, 116, 104, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 86, 97, 114, 105, 97, 110, 116, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 49, 51, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 71, 117, 105, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 71, 117, 105, 100, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 65, 114, 114, 97, 121, 76, 101, 110, 103, 116, 104, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 86, 97, 114, 105, 97, 110, 116, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 49, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 65, 114, 114, 97, 121, 76, 101, 110, 103, 116, 104, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 86, 97, 114, 105, 97, 110, 116, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 49, 53, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 88, 109, 108, 69, 108, 101, 109, 101, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 88, 109, 108, 69, 108, 101, 109, 101, 110, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 65, 114, 114, 97, 121, 76, 101, 110, 103, 116, 104, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 86, 97, 114, 105, 97, 110, 116, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 65, 114, 114, 97, 121, 76, 101, 110, 103, 116, 104, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 86, 97, 114, 105, 97, 110, 116, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 49, 55, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 120, 112, 97, 110, 100, 101, 100, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 112, 97, 110, 100, 101, 100, 78, 111, 100, 101, 73, 100, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 65, 114, 114, 97, 121, 76, 101, 110, 103, 116, 104, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 86, 97, 114, 105, 97, 110, 116, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 49, 56, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 65, 114, 114, 97, 121, 76, 101, 110, 103, 116, 104, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 86, 97, 114, 105, 97, 110, 116, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 49, 57, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 81, 117, 97, 108, 105, 102, 105, 101, 100, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 81, 117, 97, 108, 105, 102, 105, 101, 100, 78, 97, 109, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 65, 114, 114, 97, 121, 76, 101, 110, 103, 116, 104, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 86, 97, 114, 105, 97, 110, 116, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 50, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 65, 114, 114, 97, 121, 76, 101, 110, 103, 116, 104, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 86, 97, 114, 105, 97, 110, 116, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 50, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 65, 114, 114, 97, 121, 76, 101, 110, 103, 116, 104, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 86, 97, 114, 105, 97, 110, 116, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 50, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 86, 97, 108, 117, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 97, 116, 97, 86, 97, 108, 117, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 65, 114, 114, 97, 121, 76, 101, 110, 103, 116, 104, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 86, 97, 114, 105, 97, 110, 116, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 50, 51, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 86, 97, 114, 105, 97, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 86, 97, 114, 105, 97, 110, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 65, 114, 114, 97, 121, 76, 101, 110, 103, 116, 104, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 86, 97, 114, 105, 97, 110, 116, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 50, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 65, 114, 114, 97, 121, 76, 101, 110, 103, 116, 104, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 86, 97, 114, 105, 97, 110, 116, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 50, 53, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 65, 114, 114, 97, 121, 68, 105, 109, 101, 110, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 65, 114, 114, 97, 121, 68, 105, 109, 101, 110, 115, 105, 111, 110, 115, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 114, 114, 97, 121, 68, 105, 109, 101, 110, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 65, 114, 114, 97, 121, 68, 105, 109, 101, 110, 115, 105, 111, 110, 115, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 65, 114, 114, 97, 121, 68, 105, 109, 101, 110, 115, 105, 111, 110, 115, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 105, 110, 103, 82, 117, 108, 101, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 77, 97, 110, 100, 97, 116, 111, 114, 121, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 79, 112, 116, 105, 111, 110, 97, 108, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 67, 111, 110, 115, 116, 114, 97, 105, 110, 116, 34, 32, 86, 97, 108, 117, 101, 61, 34, 51, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 32, 32, 32, 32, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 73, 109, 97, 103, 101, 66, 77, 80, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 73, 109, 97, 103, 101, 71, 73, 70, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 73, 109, 97, 103, 101, 74, 80, 71, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 73, 109, 97, 103, 101, 80, 78, 71, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 65, 117, 100, 105, 111, 68, 97, 116, 97, 84, 121, 112, 101, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 66, 105, 116, 70, 105, 101, 108, 100, 77, 97, 115, 107, 68, 97, 116, 97, 84, 121, 112, 101, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 75, 101, 121, 86, 97, 108, 117, 101, 80, 97, 105, 114, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 75, 101, 121, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 81, 117, 97, 108, 105, 102, 105, 101, 100, 78, 97, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 86, 97, 108, 117, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 86, 97, 114, 105, 97, 110, 116, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 65, 100, 100, 105, 116, 105, 111, 110, 97, 108, 80, 97, 114, 97, 109, 101, 116, 101, 114, 115, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 80, 97, 114, 97, 109, 101, 116, 101, 114, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 97, 114, 97, 109, 101, 116, 101, 114, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 75, 101, 121, 86, 97, 108, 117, 101, 80, 97, 105, 114, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 80, 97, 114, 97, 109, 101, 116, 101, 114, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 69, 112, 104, 101, 109, 101, 114, 97, 108, 75, 101, 121, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 117, 98, 108, 105, 99, 75, 101, 121, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 105, 103, 110, 97, 116, 117, 114, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 69, 110, 100, 112, 111, 105, 110, 116, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 110, 100, 112, 111, 105, 110, 116, 85, 114, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 99, 117, 114, 105, 116, 121, 77, 111, 100, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 77, 101, 115, 115, 97, 103, 101, 83, 101, 99, 117, 114, 105, 116, 121, 77, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 99, 117, 114, 105, 116, 121, 80, 111, 108, 105, 99, 121, 85, 114, 105, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 114, 97, 110, 115, 112, 111, 114, 116, 80, 114, 111, 102, 105, 108, 101, 85, 114, 105, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 82, 97, 116, 105, 111, 110, 97, 108, 78, 117, 109, 98, 101, 114, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 117, 109, 101, 114, 97, 116, 111, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 110, 111, 109, 105, 110, 97, 116, 111, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 86, 101, 99, 116, 111, 114, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 84, 104, 114, 101, 101, 68, 86, 101, 99, 116, 111, 114, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 86, 101, 99, 116, 111, 114, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 88, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 89, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 90, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 67, 97, 114, 116, 101, 115, 105, 97, 110, 67, 111, 111, 114, 100, 105, 110, 97, 116, 101, 115, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 84, 104, 114, 101, 101, 68, 67, 97, 114, 116, 101, 115, 105, 97, 110, 67, 111, 111, 114, 100, 105, 110, 97, 116, 101, 115, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 67, 97, 114, 116, 101, 115, 105, 97, 110, 67, 111, 111, 114, 100, 105, 110, 97, 116, 101, 115, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 88, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 89, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 90, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 79, 114, 105, 101, 110, 116, 97, 116, 105, 111, 110, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 84, 104, 114, 101, 101, 68, 79, 114, 105, 101, 110, 116, 97, 116, 105, 111, 110, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 79, 114, 105, 101, 110, 116, 97, 116, 105, 111, 110, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 70, 114, 97, 109, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 84, 104, 114, 101, 101, 68, 70, 114, 97, 109, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 70, 114, 97, 109, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 97, 114, 116, 101, 115, 105, 97, 110, 67, 111, 111, 114, 100, 105, 110, 97, 116, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 84, 104, 114, 101, 101, 68, 67, 97, 114, 116, 101, 115, 105, 97, 110, 67, 111, 111, 114, 100, 105, 110, 97, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 79, 114, 105, 101, 110, 116, 97, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 84, 104, 114, 101, 101, 68, 79, 114, 105, 101, 110, 116, 97, 116, 105, 111, 110, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 79, 112, 101, 110, 70, 105, 108, 101, 77, 111, 100, 101, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 97, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 69, 114, 97, 115, 101, 69, 120, 105, 115, 116, 105, 110, 103, 34, 32, 86, 97, 108, 117, 101, 61, 34, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 65, 112, 112, 101, 110, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 56, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 73, 100, 101, 110, 116, 105, 116, 121, 67, 114, 105, 116, 101, 114, 105, 97, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 78, 97, 109, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 84, 104, 117, 109, 98, 112, 114, 105, 110, 116, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 82, 111, 108, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 51, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 71, 114, 111, 117, 112, 73, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 65, 110, 111, 110, 121, 109, 111, 117, 115, 34, 32, 86, 97, 108, 117, 101, 61, 34, 53, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 65, 117, 116, 104, 101, 110, 116, 105, 99, 97, 116, 101, 100, 85, 115, 101, 114, 34, 32, 86, 97, 108, 117, 101, 61, 34, 54, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 73, 100, 101, 110, 116, 105, 116, 121, 77, 97, 112, 112, 105, 110, 103, 82, 117, 108, 101, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 114, 105, 116, 101, 114, 105, 97, 84, 121, 112, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 73, 100, 101, 110, 116, 105, 116, 121, 67, 114, 105, 116, 101, 114, 105, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 114, 105, 116, 101, 114, 105, 97, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 67, 117, 114, 114, 101, 110, 99, 121, 85, 110, 105, 116, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 117, 109, 101, 114, 105, 99, 67, 111, 100, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 120, 112, 111, 110, 101, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 66, 121, 116, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 108, 112, 104, 97, 98, 101, 116, 105, 99, 67, 111, 100, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 117, 114, 114, 101, 110, 99, 121, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 84, 114, 117, 115, 116, 76, 105, 115, 116, 77, 97, 115, 107, 115, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 110, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 84, 114, 117, 115, 116, 101, 100, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 115, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 84, 114, 117, 115, 116, 101, 100, 67, 114, 108, 115, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 73, 115, 115, 117, 101, 114, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 115, 34, 32, 86, 97, 108, 117, 101, 61, 34, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 73, 115, 115, 117, 101, 114, 67, 114, 108, 115, 34, 32, 86, 97, 108, 117, 101, 61, 34, 56, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 65, 108, 108, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 53, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 84, 114, 117, 115, 116, 76, 105, 115, 116, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 112, 101, 99, 105, 102, 105, 101, 100, 76, 105, 115, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 84, 114, 117, 115, 116, 101, 100, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 114, 117, 115, 116, 101, 100, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 84, 114, 117, 115, 116, 101, 100, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 84, 114, 117, 115, 116, 101, 100, 67, 114, 108, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 114, 117, 115, 116, 101, 100, 67, 114, 108, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 84, 114, 117, 115, 116, 101, 100, 67, 114, 108, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 73, 115, 115, 117, 101, 114, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 115, 115, 117, 101, 114, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 73, 115, 115, 117, 101, 114, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 73, 115, 115, 117, 101, 114, 67, 114, 108, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 115, 115, 117, 101, 114, 67, 114, 108, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 73, 115, 115, 117, 101, 114, 67, 114, 108, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 101, 99, 105, 109, 97, 108, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 99, 97, 108, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 86, 97, 108, 117, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 84, 121, 112, 101, 83, 99, 104, 101, 109, 97, 72, 101, 97, 100, 101, 114, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 78, 97, 109, 101, 115, 112, 97, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 101, 115, 112, 97, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 78, 97, 109, 101, 115, 112, 97, 99, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 83, 116, 114, 117, 99, 116, 117, 114, 101, 68, 97, 116, 97, 84, 121, 112, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 116, 114, 117, 99, 116, 117, 114, 101, 68, 97, 116, 97, 84, 121, 112, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 83, 116, 114, 117, 99, 116, 117, 114, 101, 68, 97, 116, 97, 84, 121, 112, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 69, 110, 117, 109, 68, 97, 116, 97, 84, 121, 112, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 110, 117, 109, 68, 97, 116, 97, 84, 121, 112, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 69, 110, 117, 109, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 69, 110, 117, 109, 68, 97, 116, 97, 84, 121, 112, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 83, 105, 109, 112, 108, 101, 68, 97, 116, 97, 84, 121, 112, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 105, 109, 112, 108, 101, 68, 97, 116, 97, 84, 121, 112, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 105, 109, 112, 108, 101, 84, 121, 112, 101, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 83, 105, 109, 112, 108, 101, 68, 97, 116, 97, 84, 121, 112, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 84, 121, 112, 101, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 84, 121, 112, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 81, 117, 97, 108, 105, 102, 105, 101, 100, 78, 97, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 116, 114, 117, 99, 116, 117, 114, 101, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 68, 97, 116, 97, 84, 121, 112, 101, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 84, 121, 112, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 68, 97, 116, 97, 84, 121, 112, 101, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 81, 117, 97, 108, 105, 102, 105, 101, 100, 78, 97, 109, 101, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 68, 97, 116, 97, 84, 121, 112, 101, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 116, 114, 117, 99, 116, 117, 114, 101, 68, 101, 102, 105, 110, 105, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 68, 101, 102, 105, 110, 105, 116, 105, 111, 110, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 69, 110, 117, 109, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 68, 97, 116, 97, 84, 121, 112, 101, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 84, 121, 112, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 68, 97, 116, 97, 84, 121, 112, 101, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 81, 117, 97, 108, 105, 102, 105, 101, 100, 78, 97, 109, 101, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 68, 97, 116, 97, 84, 121, 112, 101, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 110, 117, 109, 68, 101, 102, 105, 110, 105, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 69, 110, 117, 109, 68, 101, 102, 105, 110, 105, 116, 105, 111, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 117, 105, 108, 116, 73, 110, 84, 121, 112, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 105, 109, 112, 108, 101, 84, 121, 112, 101, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 68, 97, 116, 97, 84, 121, 112, 101, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 84, 121, 112, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 68, 97, 116, 97, 84, 121, 112, 101, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 81, 117, 97, 108, 105, 102, 105, 101, 100, 78, 97, 109, 101, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 68, 97, 116, 97, 84, 121, 112, 101, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 97, 115, 101, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 117, 105, 108, 116, 73, 110, 84, 121, 112, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 85, 65, 66, 105, 110, 97, 114, 121, 70, 105, 108, 101, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 68, 97, 116, 97, 84, 121, 112, 101, 83, 99, 104, 101, 109, 97, 72, 101, 97, 100, 101, 114, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 78, 97, 109, 101, 115, 112, 97, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 101, 115, 112, 97, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 78, 97, 109, 101, 115, 112, 97, 99, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 83, 116, 114, 117, 99, 116, 117, 114, 101, 68, 97, 116, 97, 84, 121, 112, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 116, 114, 117, 99, 116, 117, 114, 101, 68, 97, 116, 97, 84, 121, 112, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 83, 116, 114, 117, 99, 116, 117, 114, 101, 68, 97, 116, 97, 84, 121, 112, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 69, 110, 117, 109, 68, 97, 116, 97, 84, 121, 112, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 110, 117, 109, 68, 97, 116, 97, 84, 121, 112, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 69, 110, 117, 109, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 69, 110, 117, 109, 68, 97, 116, 97, 84, 121, 112, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 83, 105, 109, 112, 108, 101, 68, 97, 116, 97, 84, 121, 112, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 105, 109, 112, 108, 101, 68, 97, 116, 97, 84, 121, 112, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 105, 109, 112, 108, 101, 84, 121, 112, 101, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 83, 105, 109, 112, 108, 101, 68, 97, 116, 97, 84, 121, 112, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 99, 104, 101, 109, 97, 76, 111, 99, 97, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 70, 105, 108, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 70, 105, 108, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 75, 101, 121, 86, 97, 108, 117, 101, 80, 97, 105, 114, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 70, 105, 108, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 111, 100, 121, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 86, 97, 114, 105, 97, 110, 116, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 80, 117, 98, 83, 117, 98, 83, 116, 97, 116, 101, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 97, 98, 108, 101, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 80, 97, 117, 115, 101, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 79, 112, 101, 114, 97, 116, 105, 111, 110, 97, 108, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 69, 114, 114, 111, 114, 34, 32, 86, 97, 108, 117, 101, 61, 34, 51, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 77, 101, 116, 97, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 68, 97, 116, 97, 84, 121, 112, 101, 83, 99, 104, 101, 109, 97, 72, 101, 97, 100, 101, 114, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 78, 97, 109, 101, 115, 112, 97, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 101, 115, 112, 97, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 78, 97, 109, 101, 115, 112, 97, 99, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 83, 116, 114, 117, 99, 116, 117, 114, 101, 68, 97, 116, 97, 84, 121, 112, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 116, 114, 117, 99, 116, 117, 114, 101, 68, 97, 116, 97, 84, 121, 112, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 83, 116, 114, 117, 99, 116, 117, 114, 101, 68, 97, 116, 97, 84, 121, 112, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 69, 110, 117, 109, 68, 97, 116, 97, 84, 121, 112, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 110, 117, 109, 68, 97, 116, 97, 84, 121, 112, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 69, 110, 117, 109, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 69, 110, 117, 109, 68, 97, 116, 97, 84, 121, 112, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 83, 105, 109, 112, 108, 101, 68, 97, 116, 97, 84, 121, 112, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 105, 109, 112, 108, 101, 68, 97, 116, 97, 84, 121, 112, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 105, 109, 112, 108, 101, 84, 121, 112, 101, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 83, 105, 109, 112, 108, 101, 68, 97, 116, 97, 84, 121, 112, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 70, 105, 101, 108, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 70, 105, 101, 108, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 70, 105, 101, 108, 100, 77, 101, 116, 97, 68, 97, 116, 97, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 70, 105, 101, 108, 100, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 67, 108, 97, 115, 115, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 71, 117, 105, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 111, 110, 102, 105, 103, 117, 114, 97, 116, 105, 111, 110, 86, 101, 114, 115, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 67, 111, 110, 102, 105, 103, 117, 114, 97, 116, 105, 111, 110, 86, 101, 114, 115, 105, 111, 110, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 70, 105, 101, 108, 100, 77, 101, 116, 97, 68, 97, 116, 97, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 70, 105, 101, 108, 100, 70, 108, 97, 103, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 68, 97, 116, 97, 83, 101, 116, 70, 105, 101, 108, 100, 70, 108, 97, 103, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 117, 105, 108, 116, 73, 110, 84, 121, 112, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 86, 97, 108, 117, 101, 82, 97, 110, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 65, 114, 114, 97, 121, 68, 105, 109, 101, 110, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 114, 114, 97, 121, 68, 105, 109, 101, 110, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 65, 114, 114, 97, 121, 68, 105, 109, 101, 110, 115, 105, 111, 110, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 97, 120, 83, 116, 114, 105, 110, 103, 76, 101, 110, 103, 116, 104, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 70, 105, 101, 108, 100, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 71, 117, 105, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 80, 114, 111, 112, 101, 114, 116, 105, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 114, 111, 112, 101, 114, 116, 105, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 75, 101, 121, 86, 97, 108, 117, 101, 80, 97, 105, 114, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 80, 114, 111, 112, 101, 114, 116, 105, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 70, 105, 101, 108, 100, 70, 108, 97, 103, 115, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 49, 54, 34, 32, 73, 115, 79, 112, 116, 105, 111, 110, 83, 101, 116, 61, 34, 116, 114, 117, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 110, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 80, 114, 111, 109, 111, 116, 101, 100, 70, 105, 101, 108, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 67, 111, 110, 102, 105, 103, 117, 114, 97, 116, 105, 111, 110, 86, 101, 114, 115, 105, 111, 110, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 97, 106, 111, 114, 86, 101, 114, 115, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 105, 110, 111, 114, 86, 101, 114, 115, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 80, 117, 98, 108, 105, 115, 104, 101, 100, 68, 97, 116, 97, 83, 101, 116, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 97, 116, 97, 83, 101, 116, 70, 111, 108, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 70, 111, 108, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 97, 116, 97, 83, 101, 116, 70, 111, 108, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 77, 101, 116, 97, 68, 97, 116, 97, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 68, 97, 116, 97, 83, 101, 116, 77, 101, 116, 97, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 69, 120, 116, 101, 110, 115, 105, 111, 110, 70, 105, 101, 108, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 120, 116, 101, 110, 115, 105, 111, 110, 70, 105, 101, 108, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 75, 101, 121, 86, 97, 108, 117, 101, 80, 97, 105, 114, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 69, 120, 116, 101, 110, 115, 105, 111, 110, 70, 105, 101, 108, 100, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 83, 111, 117, 114, 99, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 80, 117, 98, 108, 105, 115, 104, 101, 100, 68, 97, 116, 97, 83, 101, 116, 83, 111, 117, 114, 99, 101, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 80, 117, 98, 108, 105, 115, 104, 101, 100, 86, 97, 114, 105, 97, 98, 108, 101, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 117, 98, 108, 105, 115, 104, 101, 100, 86, 97, 114, 105, 97, 98, 108, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 116, 116, 114, 105, 98, 117, 116, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 97, 109, 112, 108, 105, 110, 103, 73, 110, 116, 101, 114, 118, 97, 108, 72, 105, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 97, 100, 98, 97, 110, 100, 84, 121, 112, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 97, 100, 98, 97, 110, 100, 86, 97, 108, 117, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 110, 100, 101, 120, 82, 97, 110, 103, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 117, 98, 115, 116, 105, 116, 117, 116, 101, 86, 97, 108, 117, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 86, 97, 114, 105, 97, 110, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 77, 101, 116, 97, 68, 97, 116, 97, 80, 114, 111, 112, 101, 114, 116, 105, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 101, 116, 97, 68, 97, 116, 97, 80, 114, 111, 112, 101, 114, 116, 105, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 81, 117, 97, 108, 105, 102, 105, 101, 100, 78, 97, 109, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 77, 101, 116, 97, 68, 97, 116, 97, 80, 114, 111, 112, 101, 114, 116, 105, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 80, 117, 98, 108, 105, 115, 104, 101, 100, 68, 97, 116, 97, 73, 116, 101, 109, 115, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 80, 117, 98, 108, 105, 115, 104, 101, 100, 68, 97, 116, 97, 83, 101, 116, 83, 111, 117, 114, 99, 101, 68, 97, 116, 97, 84, 121, 112, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 80, 117, 98, 108, 105, 115, 104, 101, 100, 68, 97, 116, 97, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 117, 98, 108, 105, 115, 104, 101, 100, 68, 97, 116, 97, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 80, 117, 98, 108, 105, 115, 104, 101, 100, 86, 97, 114, 105, 97, 98, 108, 101, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 80, 117, 98, 108, 105, 115, 104, 101, 100, 68, 97, 116, 97, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 80, 117, 98, 108, 105, 115, 104, 101, 100, 69, 118, 101, 110, 116, 115, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 80, 117, 98, 108, 105, 115, 104, 101, 100, 68, 97, 116, 97, 83, 101, 116, 83, 111, 117, 114, 99, 101, 68, 97, 116, 97, 84, 121, 112, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 118, 101, 110, 116, 78, 111, 116, 105, 102, 105, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 83, 101, 108, 101, 99, 116, 101, 100, 70, 105, 101, 108, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 108, 101, 99, 116, 101, 100, 70, 105, 101, 108, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 105, 109, 112, 108, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 79, 112, 101, 114, 97, 110, 100, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 83, 101, 108, 101, 99, 116, 101, 100, 70, 105, 101, 108, 100, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 70, 105, 108, 116, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 67, 111, 110, 116, 101, 110, 116, 70, 105, 108, 116, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 70, 105, 101, 108, 100, 67, 111, 110, 116, 101, 110, 116, 77, 97, 115, 107, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 32, 73, 115, 79, 112, 116, 105, 111, 110, 83, 101, 116, 61, 34, 116, 114, 117, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 110, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 83, 111, 117, 114, 99, 101, 84, 105, 109, 101, 115, 116, 97, 109, 112, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 84, 105, 109, 101, 115, 116, 97, 109, 112, 34, 32, 86, 97, 108, 117, 101, 61, 34, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 83, 111, 117, 114, 99, 101, 80, 105, 99, 111, 83, 101, 99, 111, 110, 100, 115, 34, 32, 86, 97, 108, 117, 101, 61, 34, 56, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 80, 105, 99, 111, 83, 101, 99, 111, 110, 100, 115, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 82, 97, 119, 68, 97, 116, 97, 34, 32, 86, 97, 108, 117, 101, 61, 34, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 87, 114, 105, 116, 101, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 110, 97, 98, 108, 101, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 87, 114, 105, 116, 101, 114, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 70, 105, 101, 108, 100, 67, 111, 110, 116, 101, 110, 116, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 68, 97, 116, 97, 83, 101, 116, 70, 105, 101, 108, 100, 67, 111, 110, 116, 101, 110, 116, 77, 97, 115, 107, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 75, 101, 121, 70, 114, 97, 109, 101, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 97, 116, 97, 83, 101, 116, 87, 114, 105, 116, 101, 114, 80, 114, 111, 112, 101, 114, 116, 105, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 87, 114, 105, 116, 101, 114, 80, 114, 111, 112, 101, 114, 116, 105, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 75, 101, 121, 86, 97, 108, 117, 101, 80, 97, 105, 114, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 97, 116, 97, 83, 101, 116, 87, 114, 105, 116, 101, 114, 80, 114, 111, 112, 101, 114, 116, 105, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 114, 97, 110, 115, 112, 111, 114, 116, 83, 101, 116, 116, 105, 110, 103, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 101, 115, 115, 97, 103, 101, 83, 101, 116, 116, 105, 110, 103, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 87, 114, 105, 116, 101, 114, 84, 114, 97, 110, 115, 112, 111, 114, 116, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 87, 114, 105, 116, 101, 114, 77, 101, 115, 115, 97, 103, 101, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 80, 117, 98, 83, 117, 98, 71, 114, 111, 117, 112, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 110, 97, 98, 108, 101, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 99, 117, 114, 105, 116, 121, 77, 111, 100, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 77, 101, 115, 115, 97, 103, 101, 83, 101, 99, 117, 114, 105, 116, 121, 77, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 99, 117, 114, 105, 116, 121, 71, 114, 111, 117, 112, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 83, 101, 99, 117, 114, 105, 116, 121, 75, 101, 121, 83, 101, 114, 118, 105, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 99, 117, 114, 105, 116, 121, 75, 101, 121, 83, 101, 114, 118, 105, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 69, 110, 100, 112, 111, 105, 110, 116, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 83, 101, 99, 117, 114, 105, 116, 121, 75, 101, 121, 83, 101, 114, 118, 105, 99, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 97, 120, 78, 101, 116, 119, 111, 114, 107, 77, 101, 115, 115, 97, 103, 101, 83, 105, 122, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 71, 114, 111, 117, 112, 80, 114, 111, 112, 101, 114, 116, 105, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 71, 114, 111, 117, 112, 80, 114, 111, 112, 101, 114, 116, 105, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 75, 101, 121, 86, 97, 108, 117, 101, 80, 97, 105, 114, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 71, 114, 111, 117, 112, 80, 114, 111, 112, 101, 114, 116, 105, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 114, 71, 114, 111, 117, 112, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 80, 117, 98, 83, 117, 98, 71, 114, 111, 117, 112, 68, 97, 116, 97, 84, 121, 112, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 80, 117, 98, 83, 117, 98, 71, 114, 111, 117, 112, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 110, 97, 98, 108, 101, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 80, 117, 98, 83, 117, 98, 71, 114, 111, 117, 112, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 99, 117, 114, 105, 116, 121, 77, 111, 100, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 77, 101, 115, 115, 97, 103, 101, 83, 101, 99, 117, 114, 105, 116, 121, 77, 111, 100, 101, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 80, 117, 98, 83, 117, 98, 71, 114, 111, 117, 112, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 99, 117, 114, 105, 116, 121, 71, 114, 111, 117, 112, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 80, 117, 98, 83, 117, 98, 71, 114, 111, 117, 112, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 83, 101, 99, 117, 114, 105, 116, 121, 75, 101, 121, 83, 101, 114, 118, 105, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 99, 117, 114, 105, 116, 121, 75, 101, 121, 83, 101, 114, 118, 105, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 69, 110, 100, 112, 111, 105, 110, 116, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 83, 101, 99, 117, 114, 105, 116, 121, 75, 101, 121, 83, 101, 114, 118, 105, 99, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 97, 120, 78, 101, 116, 119, 111, 114, 107, 77, 101, 115, 115, 97, 103, 101, 83, 105, 122, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 80, 117, 98, 83, 117, 98, 71, 114, 111, 117, 112, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 71, 114, 111, 117, 112, 80, 114, 111, 112, 101, 114, 116, 105, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 71, 114, 111, 117, 112, 80, 114, 111, 112, 101, 114, 116, 105, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 75, 101, 121, 86, 97, 108, 117, 101, 80, 97, 105, 114, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 71, 114, 111, 117, 112, 80, 114, 111, 112, 101, 114, 116, 105, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 114, 71, 114, 111, 117, 112, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 117, 98, 108, 105, 115, 104, 105, 110, 103, 73, 110, 116, 101, 114, 118, 97, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 75, 101, 101, 112, 65, 108, 105, 118, 101, 84, 105, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 114, 105, 111, 114, 105, 116, 121, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 76, 111, 99, 97, 108, 101, 73, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 76, 111, 99, 97, 108, 101, 73, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 76, 111, 99, 97, 108, 101, 73, 100, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 72, 101, 97, 100, 101, 114, 76, 97, 121, 111, 117, 116, 85, 114, 105, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 114, 97, 110, 115, 112, 111, 114, 116, 83, 101, 116, 116, 105, 110, 103, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 101, 115, 115, 97, 103, 101, 83, 101, 116, 116, 105, 110, 103, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 97, 116, 97, 83, 101, 116, 87, 114, 105, 116, 101, 114, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 87, 114, 105, 116, 101, 114, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 68, 97, 116, 97, 83, 101, 116, 87, 114, 105, 116, 101, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 97, 116, 97, 83, 101, 116, 87, 114, 105, 116, 101, 114, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 114, 71, 114, 111, 117, 112, 84, 114, 97, 110, 115, 112, 111, 114, 116, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 114, 71, 114, 111, 117, 112, 77, 101, 115, 115, 97, 103, 101, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 80, 117, 98, 83, 117, 98, 67, 111, 110, 110, 101, 99, 116, 105, 111, 110, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 110, 97, 98, 108, 101, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 117, 98, 108, 105, 115, 104, 101, 114, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 86, 97, 114, 105, 97, 110, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 114, 97, 110, 115, 112, 111, 114, 116, 80, 114, 111, 102, 105, 108, 101, 85, 114, 105, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 100, 100, 114, 101, 115, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 67, 111, 110, 110, 101, 99, 116, 105, 111, 110, 80, 114, 111, 112, 101, 114, 116, 105, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 111, 110, 110, 101, 99, 116, 105, 111, 110, 80, 114, 111, 112, 101, 114, 116, 105, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 75, 101, 121, 86, 97, 108, 117, 101, 80, 97, 105, 114, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 67, 111, 110, 110, 101, 99, 116, 105, 111, 110, 80, 114, 111, 112, 101, 114, 116, 105, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 114, 97, 110, 115, 112, 111, 114, 116, 83, 101, 116, 116, 105, 110, 103, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 87, 114, 105, 116, 101, 114, 71, 114, 111, 117, 112, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 114, 71, 114, 111, 117, 112, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 87, 114, 105, 116, 101, 114, 71, 114, 111, 117, 112, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 87, 114, 105, 116, 101, 114, 71, 114, 111, 117, 112, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 97, 100, 101, 114, 71, 114, 111, 117, 112, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 97, 100, 101, 114, 71, 114, 111, 117, 112, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 97, 100, 101, 114, 71, 114, 111, 117, 112, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 97, 100, 101, 114, 71, 114, 111, 117, 112, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 67, 111, 110, 110, 101, 99, 116, 105, 111, 110, 84, 114, 97, 110, 115, 112, 111, 114, 116, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 78, 101, 116, 119, 111, 114, 107, 65, 100, 100, 114, 101, 115, 115, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 101, 116, 119, 111, 114, 107, 73, 110, 116, 101, 114, 102, 97, 99, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 78, 101, 116, 119, 111, 114, 107, 65, 100, 100, 114, 101, 115, 115, 85, 114, 108, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 101, 116, 119, 111, 114, 107, 65, 100, 100, 114, 101, 115, 115, 68, 97, 116, 97, 84, 121, 112, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 101, 116, 119, 111, 114, 107, 73, 110, 116, 101, 114, 102, 97, 99, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 101, 116, 119, 111, 114, 107, 65, 100, 100, 114, 101, 115, 115, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 114, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 97, 100, 101, 114, 71, 114, 111, 117, 112, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 80, 117, 98, 83, 117, 98, 71, 114, 111, 117, 112, 68, 97, 116, 97, 84, 121, 112, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 80, 117, 98, 83, 117, 98, 71, 114, 111, 117, 112, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 110, 97, 98, 108, 101, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 80, 117, 98, 83, 117, 98, 71, 114, 111, 117, 112, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 99, 117, 114, 105, 116, 121, 77, 111, 100, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 77, 101, 115, 115, 97, 103, 101, 83, 101, 99, 117, 114, 105, 116, 121, 77, 111, 100, 101, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 80, 117, 98, 83, 117, 98, 71, 114, 111, 117, 112, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 99, 117, 114, 105, 116, 121, 71, 114, 111, 117, 112, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 80, 117, 98, 83, 117, 98, 71, 114, 111, 117, 112, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 83, 101, 99, 117, 114, 105, 116, 121, 75, 101, 121, 83, 101, 114, 118, 105, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 99, 117, 114, 105, 116, 121, 75, 101, 121, 83, 101, 114, 118, 105, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 69, 110, 100, 112, 111, 105, 110, 116, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 83, 101, 99, 117, 114, 105, 116, 121, 75, 101, 121, 83, 101, 114, 118, 105, 99, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 97, 120, 78, 101, 116, 119, 111, 114, 107, 77, 101, 115, 115, 97, 103, 101, 83, 105, 122, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 80, 117, 98, 83, 117, 98, 71, 114, 111, 117, 112, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 71, 114, 111, 117, 112, 80, 114, 111, 112, 101, 114, 116, 105, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 71, 114, 111, 117, 112, 80, 114, 111, 112, 101, 114, 116, 105, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 75, 101, 121, 86, 97, 108, 117, 101, 80, 97, 105, 114, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 71, 114, 111, 117, 112, 80, 114, 111, 112, 101, 114, 116, 105, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 114, 97, 110, 115, 112, 111, 114, 116, 83, 101, 116, 116, 105, 110, 103, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 101, 115, 115, 97, 103, 101, 83, 101, 116, 116, 105, 110, 103, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 97, 116, 97, 83, 101, 116, 82, 101, 97, 100, 101, 114, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 82, 101, 97, 100, 101, 114, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 68, 97, 116, 97, 83, 101, 116, 82, 101, 97, 100, 101, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 97, 116, 97, 83, 101, 116, 82, 101, 97, 100, 101, 114, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 97, 100, 101, 114, 71, 114, 111, 117, 112, 84, 114, 97, 110, 115, 112, 111, 114, 116, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 97, 100, 101, 114, 71, 114, 111, 117, 112, 77, 101, 115, 115, 97, 103, 101, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 82, 101, 97, 100, 101, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 110, 97, 98, 108, 101, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 117, 98, 108, 105, 115, 104, 101, 114, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 86, 97, 114, 105, 97, 110, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 114, 71, 114, 111, 117, 112, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 87, 114, 105, 116, 101, 114, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 77, 101, 116, 97, 68, 97, 116, 97, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 68, 97, 116, 97, 83, 101, 116, 77, 101, 116, 97, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 70, 105, 101, 108, 100, 67, 111, 110, 116, 101, 110, 116, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 68, 97, 116, 97, 83, 101, 116, 70, 105, 101, 108, 100, 67, 111, 110, 116, 101, 110, 116, 77, 97, 115, 107, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 101, 115, 115, 97, 103, 101, 82, 101, 99, 101, 105, 118, 101, 84, 105, 109, 101, 111, 117, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 75, 101, 121, 70, 114, 97, 109, 101, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 72, 101, 97, 100, 101, 114, 76, 97, 121, 111, 117, 116, 85, 114, 105, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 99, 117, 114, 105, 116, 121, 77, 111, 100, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 77, 101, 115, 115, 97, 103, 101, 83, 101, 99, 117, 114, 105, 116, 121, 77, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 99, 117, 114, 105, 116, 121, 71, 114, 111, 117, 112, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 83, 101, 99, 117, 114, 105, 116, 121, 75, 101, 121, 83, 101, 114, 118, 105, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 99, 117, 114, 105, 116, 121, 75, 101, 121, 83, 101, 114, 118, 105, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 69, 110, 100, 112, 111, 105, 110, 116, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 83, 101, 99, 117, 114, 105, 116, 121, 75, 101, 121, 83, 101, 114, 118, 105, 99, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 97, 116, 97, 83, 101, 116, 82, 101, 97, 100, 101, 114, 80, 114, 111, 112, 101, 114, 116, 105, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 82, 101, 97, 100, 101, 114, 80, 114, 111, 112, 101, 114, 116, 105, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 75, 101, 121, 86, 97, 108, 117, 101, 80, 97, 105, 114, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 97, 116, 97, 83, 101, 116, 82, 101, 97, 100, 101, 114, 80, 114, 111, 112, 101, 114, 116, 105, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 114, 97, 110, 115, 112, 111, 114, 116, 83, 101, 116, 116, 105, 110, 103, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 101, 115, 115, 97, 103, 101, 83, 101, 116, 116, 105, 110, 103, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 117, 98, 115, 99, 114, 105, 98, 101, 100, 68, 97, 116, 97, 83, 101, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 82, 101, 97, 100, 101, 114, 84, 114, 97, 110, 115, 112, 111, 114, 116, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 82, 101, 97, 100, 101, 114, 77, 101, 115, 115, 97, 103, 101, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 117, 98, 115, 99, 114, 105, 98, 101, 100, 68, 97, 116, 97, 83, 101, 116, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 84, 97, 114, 103, 101, 116, 86, 97, 114, 105, 97, 98, 108, 101, 115, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 83, 117, 98, 115, 99, 114, 105, 98, 101, 100, 68, 97, 116, 97, 83, 101, 116, 68, 97, 116, 97, 84, 121, 112, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 84, 97, 114, 103, 101, 116, 86, 97, 114, 105, 97, 98, 108, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 97, 114, 103, 101, 116, 86, 97, 114, 105, 97, 98, 108, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 70, 105, 101, 108, 100, 84, 97, 114, 103, 101, 116, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 84, 97, 114, 103, 101, 116, 86, 97, 114, 105, 97, 98, 108, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 70, 105, 101, 108, 100, 84, 97, 114, 103, 101, 116, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 70, 105, 101, 108, 100, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 71, 117, 105, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 99, 101, 105, 118, 101, 114, 73, 110, 100, 101, 120, 82, 97, 110, 103, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 97, 114, 103, 101, 116, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 116, 116, 114, 105, 98, 117, 116, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 73, 110, 100, 101, 120, 82, 97, 110, 103, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 79, 118, 101, 114, 114, 105, 100, 101, 86, 97, 108, 117, 101, 72, 97, 110, 100, 108, 105, 110, 103, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 79, 118, 101, 114, 114, 105, 100, 101, 86, 97, 108, 117, 101, 72, 97, 110, 100, 108, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 79, 118, 101, 114, 114, 105, 100, 101, 86, 97, 108, 117, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 86, 97, 114, 105, 97, 110, 116, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 79, 118, 101, 114, 114, 105, 100, 101, 86, 97, 108, 117, 101, 72, 97, 110, 100, 108, 105, 110, 103, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 97, 98, 108, 101, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 76, 97, 115, 116, 85, 115, 97, 98, 108, 101, 86, 97, 108, 117, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 79, 118, 101, 114, 114, 105, 100, 101, 86, 97, 108, 117, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 117, 98, 115, 99, 114, 105, 98, 101, 100, 68, 97, 116, 97, 83, 101, 116, 77, 105, 114, 114, 111, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 83, 117, 98, 115, 99, 114, 105, 98, 101, 100, 68, 97, 116, 97, 83, 101, 116, 68, 97, 116, 97, 84, 121, 112, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 97, 114, 101, 110, 116, 78, 111, 100, 101, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 80, 117, 98, 83, 117, 98, 67, 111, 110, 102, 105, 103, 117, 114, 97, 116, 105, 111, 110, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 80, 117, 98, 108, 105, 115, 104, 101, 100, 68, 97, 116, 97, 83, 101, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 117, 98, 108, 105, 115, 104, 101, 100, 68, 97, 116, 97, 83, 101, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 80, 117, 98, 108, 105, 115, 104, 101, 100, 68, 97, 116, 97, 83, 101, 116, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 80, 117, 98, 108, 105, 115, 104, 101, 100, 68, 97, 116, 97, 83, 101, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 67, 111, 110, 110, 101, 99, 116, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 111, 110, 110, 101, 99, 116, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 80, 117, 98, 83, 117, 98, 67, 111, 110, 110, 101, 99, 116, 105, 111, 110, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 67, 111, 110, 110, 101, 99, 116, 105, 111, 110, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 110, 97, 98, 108, 101, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 79, 114, 100, 101, 114, 105, 110, 103, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 85, 110, 100, 101, 102, 105, 110, 101, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 65, 115, 99, 101, 110, 100, 105, 110, 103, 87, 114, 105, 116, 101, 114, 73, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 65, 115, 99, 101, 110, 100, 105, 110, 103, 87, 114, 105, 116, 101, 114, 73, 100, 83, 105, 110, 103, 108, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 85, 97, 100, 112, 78, 101, 116, 119, 111, 114, 107, 77, 101, 115, 115, 97, 103, 101, 67, 111, 110, 116, 101, 110, 116, 77, 97, 115, 107, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 32, 73, 115, 79, 112, 116, 105, 111, 110, 83, 101, 116, 61, 34, 116, 114, 117, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 110, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 80, 117, 98, 108, 105, 115, 104, 101, 114, 73, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 71, 114, 111, 117, 112, 72, 101, 97, 100, 101, 114, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 114, 71, 114, 111, 117, 112, 73, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 71, 114, 111, 117, 112, 86, 101, 114, 115, 105, 111, 110, 34, 32, 86, 97, 108, 117, 101, 61, 34, 56, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 101, 116, 119, 111, 114, 107, 77, 101, 115, 115, 97, 103, 101, 78, 117, 109, 98, 101, 114, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 83, 101, 113, 117, 101, 110, 99, 101, 78, 117, 109, 98, 101, 114, 34, 32, 86, 97, 108, 117, 101, 61, 34, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 80, 97, 121, 108, 111, 97, 100, 72, 101, 97, 100, 101, 114, 34, 32, 86, 97, 108, 117, 101, 61, 34, 54, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 84, 105, 109, 101, 115, 116, 97, 109, 112, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 50, 56, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 80, 105, 99, 111, 83, 101, 99, 111, 110, 100, 115, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 53, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 67, 108, 97, 115, 115, 73, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 53, 49, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 80, 114, 111, 109, 111, 116, 101, 100, 70, 105, 101, 108, 100, 115, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 48, 50, 52, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 85, 97, 100, 112, 87, 114, 105, 116, 101, 114, 71, 114, 111, 117, 112, 77, 101, 115, 115, 97, 103, 101, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 87, 114, 105, 116, 101, 114, 71, 114, 111, 117, 112, 77, 101, 115, 115, 97, 103, 101, 68, 97, 116, 97, 84, 121, 112, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 71, 114, 111, 117, 112, 86, 101, 114, 115, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 79, 114, 100, 101, 114, 105, 110, 103, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 68, 97, 116, 97, 83, 101, 116, 79, 114, 100, 101, 114, 105, 110, 103, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 101, 116, 119, 111, 114, 107, 77, 101, 115, 115, 97, 103, 101, 67, 111, 110, 116, 101, 110, 116, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 85, 97, 100, 112, 78, 101, 116, 119, 111, 114, 107, 77, 101, 115, 115, 97, 103, 101, 67, 111, 110, 116, 101, 110, 116, 77, 97, 115, 107, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 97, 109, 112, 108, 105, 110, 103, 79, 102, 102, 115, 101, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 80, 117, 98, 108, 105, 115, 104, 105, 110, 103, 79, 102, 102, 115, 101, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 117, 98, 108, 105, 115, 104, 105, 110, 103, 79, 102, 102, 115, 101, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 80, 117, 98, 108, 105, 115, 104, 105, 110, 103, 79, 102, 102, 115, 101, 116, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 85, 97, 100, 112, 68, 97, 116, 97, 83, 101, 116, 77, 101, 115, 115, 97, 103, 101, 67, 111, 110, 116, 101, 110, 116, 77, 97, 115, 107, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 32, 73, 115, 79, 112, 116, 105, 111, 110, 83, 101, 116, 61, 34, 116, 114, 117, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 110, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 84, 105, 109, 101, 115, 116, 97, 109, 112, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 80, 105, 99, 111, 83, 101, 99, 111, 110, 100, 115, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 116, 117, 115, 34, 32, 86, 97, 108, 117, 101, 61, 34, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 77, 97, 106, 111, 114, 86, 101, 114, 115, 105, 111, 110, 34, 32, 86, 97, 108, 117, 101, 61, 34, 56, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 77, 105, 110, 111, 114, 86, 101, 114, 115, 105, 111, 110, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 83, 101, 113, 117, 101, 110, 99, 101, 78, 117, 109, 98, 101, 114, 34, 32, 86, 97, 108, 117, 101, 61, 34, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 85, 97, 100, 112, 68, 97, 116, 97, 83, 101, 116, 87, 114, 105, 116, 101, 114, 77, 101, 115, 115, 97, 103, 101, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 68, 97, 116, 97, 83, 101, 116, 87, 114, 105, 116, 101, 114, 77, 101, 115, 115, 97, 103, 101, 68, 97, 116, 97, 84, 121, 112, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 77, 101, 115, 115, 97, 103, 101, 67, 111, 110, 116, 101, 110, 116, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 85, 97, 100, 112, 68, 97, 116, 97, 83, 101, 116, 77, 101, 115, 115, 97, 103, 101, 67, 111, 110, 116, 101, 110, 116, 77, 97, 115, 107, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 111, 110, 102, 105, 103, 117, 114, 101, 100, 83, 105, 122, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 101, 116, 119, 111, 114, 107, 77, 101, 115, 115, 97, 103, 101, 78, 117, 109, 98, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 79, 102, 102, 115, 101, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 85, 97, 100, 112, 68, 97, 116, 97, 83, 101, 116, 82, 101, 97, 100, 101, 114, 77, 101, 115, 115, 97, 103, 101, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 68, 97, 116, 97, 83, 101, 116, 82, 101, 97, 100, 101, 114, 77, 101, 115, 115, 97, 103, 101, 68, 97, 116, 97, 84, 121, 112, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 71, 114, 111, 117, 112, 86, 101, 114, 115, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 101, 116, 119, 111, 114, 107, 77, 101, 115, 115, 97, 103, 101, 78, 117, 109, 98, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 79, 102, 102, 115, 101, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 67, 108, 97, 115, 115, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 71, 117, 105, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 101, 116, 119, 111, 114, 107, 77, 101, 115, 115, 97, 103, 101, 67, 111, 110, 116, 101, 110, 116, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 85, 97, 100, 112, 78, 101, 116, 119, 111, 114, 107, 77, 101, 115, 115, 97, 103, 101, 67, 111, 110, 116, 101, 110, 116, 77, 97, 115, 107, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 77, 101, 115, 115, 97, 103, 101, 67, 111, 110, 116, 101, 110, 116, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 85, 97, 100, 112, 68, 97, 116, 97, 83, 101, 116, 77, 101, 115, 115, 97, 103, 101, 67, 111, 110, 116, 101, 110, 116, 77, 97, 115, 107, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 117, 98, 108, 105, 115, 104, 105, 110, 103, 73, 110, 116, 101, 114, 118, 97, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 99, 101, 105, 118, 101, 79, 102, 102, 115, 101, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 114, 111, 99, 101, 115, 115, 105, 110, 103, 79, 102, 102, 115, 101, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 74, 115, 111, 110, 78, 101, 116, 119, 111, 114, 107, 77, 101, 115, 115, 97, 103, 101, 67, 111, 110, 116, 101, 110, 116, 77, 97, 115, 107, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 32, 73, 115, 79, 112, 116, 105, 111, 110, 83, 101, 116, 61, 34, 116, 114, 117, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 110, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 101, 116, 119, 111, 114, 107, 77, 101, 115, 115, 97, 103, 101, 72, 101, 97, 100, 101, 114, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 77, 101, 115, 115, 97, 103, 101, 72, 101, 97, 100, 101, 114, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 83, 105, 110, 103, 108, 101, 68, 97, 116, 97, 83, 101, 116, 77, 101, 115, 115, 97, 103, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 80, 117, 98, 108, 105, 115, 104, 101, 114, 73, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 56, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 67, 108, 97, 115, 115, 73, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 112, 108, 121, 84, 111, 34, 32, 86, 97, 108, 117, 101, 61, 34, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 74, 115, 111, 110, 87, 114, 105, 116, 101, 114, 71, 114, 111, 117, 112, 77, 101, 115, 115, 97, 103, 101, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 87, 114, 105, 116, 101, 114, 71, 114, 111, 117, 112, 77, 101, 115, 115, 97, 103, 101, 68, 97, 116, 97, 84, 121, 112, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 101, 116, 119, 111, 114, 107, 77, 101, 115, 115, 97, 103, 101, 67, 111, 110, 116, 101, 110, 116, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 74, 115, 111, 110, 78, 101, 116, 119, 111, 114, 107, 77, 101, 115, 115, 97, 103, 101, 67, 111, 110, 116, 101, 110, 116, 77, 97, 115, 107, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 74, 115, 111, 110, 68, 97, 116, 97, 83, 101, 116, 77, 101, 115, 115, 97, 103, 101, 67, 111, 110, 116, 101, 110, 116, 77, 97, 115, 107, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 32, 73, 115, 79, 112, 116, 105, 111, 110, 83, 101, 116, 61, 34, 116, 114, 117, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 110, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 87, 114, 105, 116, 101, 114, 73, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 77, 101, 116, 97, 68, 97, 116, 97, 86, 101, 114, 115, 105, 111, 110, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 83, 101, 113, 117, 101, 110, 99, 101, 78, 117, 109, 98, 101, 114, 34, 32, 86, 97, 108, 117, 101, 61, 34, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 84, 105, 109, 101, 115, 116, 97, 109, 112, 34, 32, 86, 97, 108, 117, 101, 61, 34, 56, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 116, 117, 115, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 74, 115, 111, 110, 68, 97, 116, 97, 83, 101, 116, 87, 114, 105, 116, 101, 114, 77, 101, 115, 115, 97, 103, 101, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 68, 97, 116, 97, 83, 101, 116, 87, 114, 105, 116, 101, 114, 77, 101, 115, 115, 97, 103, 101, 68, 97, 116, 97, 84, 121, 112, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 77, 101, 115, 115, 97, 103, 101, 67, 111, 110, 116, 101, 110, 116, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 74, 115, 111, 110, 68, 97, 116, 97, 83, 101, 116, 77, 101, 115, 115, 97, 103, 101, 67, 111, 110, 116, 101, 110, 116, 77, 97, 115, 107, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 74, 115, 111, 110, 68, 97, 116, 97, 83, 101, 116, 82, 101, 97, 100, 101, 114, 77, 101, 115, 115, 97, 103, 101, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 68, 97, 116, 97, 83, 101, 116, 82, 101, 97, 100, 101, 114, 77, 101, 115, 115, 97, 103, 101, 68, 97, 116, 97, 84, 121, 112, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 101, 116, 119, 111, 114, 107, 77, 101, 115, 115, 97, 103, 101, 67, 111, 110, 116, 101, 110, 116, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 74, 115, 111, 110, 78, 101, 116, 119, 111, 114, 107, 77, 101, 115, 115, 97, 103, 101, 67, 111, 110, 116, 101, 110, 116, 77, 97, 115, 107, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 77, 101, 115, 115, 97, 103, 101, 67, 111, 110, 116, 101, 110, 116, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 74, 115, 111, 110, 68, 97, 116, 97, 83, 101, 116, 77, 101, 115, 115, 97, 103, 101, 67, 111, 110, 116, 101, 110, 116, 77, 97, 115, 107, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 103, 114, 97, 109, 67, 111, 110, 110, 101, 99, 116, 105, 111, 110, 84, 114, 97, 110, 115, 112, 111, 114, 116, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 67, 111, 110, 110, 101, 99, 116, 105, 111, 110, 84, 114, 97, 110, 115, 112, 111, 114, 116, 68, 97, 116, 97, 84, 121, 112, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 99, 111, 118, 101, 114, 121, 65, 100, 100, 114, 101, 115, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 103, 114, 97, 109, 87, 114, 105, 116, 101, 114, 71, 114, 111, 117, 112, 84, 114, 97, 110, 115, 112, 111, 114, 116, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 87, 114, 105, 116, 101, 114, 71, 114, 111, 117, 112, 84, 114, 97, 110, 115, 112, 111, 114, 116, 68, 97, 116, 97, 84, 121, 112, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 101, 115, 115, 97, 103, 101, 82, 101, 112, 101, 97, 116, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 101, 115, 115, 97, 103, 101, 82, 101, 112, 101, 97, 116, 68, 101, 108, 97, 121, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 107, 101, 114, 67, 111, 110, 110, 101, 99, 116, 105, 111, 110, 84, 114, 97, 110, 115, 112, 111, 114, 116, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 67, 111, 110, 110, 101, 99, 116, 105, 111, 110, 84, 114, 97, 110, 115, 112, 111, 114, 116, 68, 97, 116, 97, 84, 121, 112, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 111, 117, 114, 99, 101, 85, 114, 105, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 117, 116, 104, 101, 110, 116, 105, 99, 97, 116, 105, 111, 110, 80, 114, 111, 102, 105, 108, 101, 85, 114, 105, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 107, 101, 114, 84, 114, 97, 110, 115, 112, 111, 114, 116, 81, 117, 97, 108, 105, 116, 121, 79, 102, 83, 101, 114, 118, 105, 99, 101, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 116, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 66, 101, 115, 116, 69, 102, 102, 111, 114, 116, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 65, 116, 76, 101, 97, 115, 116, 79, 110, 99, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 65, 116, 77, 111, 115, 116, 79, 110, 99, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 51, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 69, 120, 97, 99, 116, 108, 121, 79, 110, 99, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 52, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 107, 101, 114, 87, 114, 105, 116, 101, 114, 71, 114, 111, 117, 112, 84, 114, 97, 110, 115, 112, 111, 114, 116, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 87, 114, 105, 116, 101, 114, 71, 114, 111, 117, 112, 84, 114, 97, 110, 115, 112, 111, 114, 116, 68, 97, 116, 97, 84, 121, 112, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 81, 117, 101, 117, 101, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 111, 117, 114, 99, 101, 85, 114, 105, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 117, 116, 104, 101, 110, 116, 105, 99, 97, 116, 105, 111, 110, 80, 114, 111, 102, 105, 108, 101, 85, 114, 105, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 101, 100, 68, 101, 108, 105, 118, 101, 114, 121, 71, 117, 97, 114, 97, 110, 116, 101, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 66, 114, 111, 107, 101, 114, 84, 114, 97, 110, 115, 112, 111, 114, 116, 81, 117, 97, 108, 105, 116, 121, 79, 102, 83, 101, 114, 118, 105, 99, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 107, 101, 114, 68, 97, 116, 97, 83, 101, 116, 87, 114, 105, 116, 101, 114, 84, 114, 97, 110, 115, 112, 111, 114, 116, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 68, 97, 116, 97, 83, 101, 116, 87, 114, 105, 116, 101, 114, 84, 114, 97, 110, 115, 112, 111, 114, 116, 68, 97, 116, 97, 84, 121, 112, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 81, 117, 101, 117, 101, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 111, 117, 114, 99, 101, 85, 114, 105, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 117, 116, 104, 101, 110, 116, 105, 99, 97, 116, 105, 111, 110, 80, 114, 111, 102, 105, 108, 101, 85, 114, 105, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 101, 100, 68, 101, 108, 105, 118, 101, 114, 121, 71, 117, 97, 114, 97, 110, 116, 101, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 66, 114, 111, 107, 101, 114, 84, 114, 97, 110, 115, 112, 111, 114, 116, 81, 117, 97, 108, 105, 116, 121, 79, 102, 83, 101, 114, 118, 105, 99, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 101, 116, 97, 68, 97, 116, 97, 81, 117, 101, 117, 101, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 101, 116, 97, 68, 97, 116, 97, 85, 112, 100, 97, 116, 101, 84, 105, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 107, 101, 114, 68, 97, 116, 97, 83, 101, 116, 82, 101, 97, 100, 101, 114, 84, 114, 97, 110, 115, 112, 111, 114, 116, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 68, 97, 116, 97, 83, 101, 116, 82, 101, 97, 100, 101, 114, 84, 114, 97, 110, 115, 112, 111, 114, 116, 68, 97, 116, 97, 84, 121, 112, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 81, 117, 101, 117, 101, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 111, 117, 114, 99, 101, 85, 114, 105, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 117, 116, 104, 101, 110, 116, 105, 99, 97, 116, 105, 111, 110, 80, 114, 111, 102, 105, 108, 101, 85, 114, 105, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 101, 100, 68, 101, 108, 105, 118, 101, 114, 121, 71, 117, 97, 114, 97, 110, 116, 101, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 66, 114, 111, 107, 101, 114, 84, 114, 97, 110, 115, 112, 111, 114, 116, 81, 117, 97, 108, 105, 116, 121, 79, 102, 83, 101, 114, 118, 105, 99, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 101, 116, 97, 68, 97, 116, 97, 81, 117, 101, 117, 101, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 115, 76, 101, 118, 101, 108, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 66, 97, 115, 105, 99, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 65, 100, 118, 97, 110, 99, 101, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 73, 110, 102, 111, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 76, 111, 103, 34, 32, 86, 97, 108, 117, 101, 61, 34, 51, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 68, 101, 98, 117, 103, 34, 32, 86, 97, 108, 117, 101, 61, 34, 52, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 80, 117, 98, 83, 117, 98, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 115, 67, 111, 117, 110, 116, 101, 114, 67, 108, 97, 115, 115, 105, 102, 105, 99, 97, 116, 105, 111, 110, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 73, 110, 102, 111, 114, 109, 97, 116, 105, 111, 110, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 69, 114, 114, 111, 114, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 65, 108, 105, 97, 115, 78, 97, 109, 101, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 108, 105, 97, 115, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 81, 117, 97, 108, 105, 102, 105, 101, 100, 78, 97, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 102, 101, 114, 101, 110, 99, 101, 100, 78, 111, 100, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 102, 101, 114, 101, 110, 99, 101, 100, 78, 111, 100, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 112, 97, 110, 100, 101, 100, 78, 111, 100, 101, 73, 100, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 102, 101, 114, 101, 110, 99, 101, 100, 78, 111, 100, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 73, 100, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 117, 109, 101, 114, 105, 99, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 83, 116, 114, 105, 110, 103, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 71, 117, 105, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 79, 112, 97, 113, 117, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 51, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 67, 108, 97, 115, 115, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 85, 110, 115, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 79, 98, 106, 101, 99, 116, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 86, 97, 114, 105, 97, 98, 108, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 77, 101, 116, 104, 111, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 79, 98, 106, 101, 99, 116, 84, 121, 112, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 56, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 86, 97, 114, 105, 97, 98, 108, 101, 84, 121, 112, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 102, 101, 114, 101, 110, 99, 101, 84, 121, 112, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 54, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 86, 105, 101, 119, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 50, 56, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 32, 73, 115, 79, 112, 116, 105, 111, 110, 83, 101, 116, 61, 34, 116, 114, 117, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 110, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 119, 115, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 97, 100, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 86, 97, 108, 117, 101, 61, 34, 56, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 72, 105, 115, 116, 111, 114, 105, 122, 105, 110, 103, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 97, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 54, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 97, 100, 72, 105, 115, 116, 111, 114, 121, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 50, 56, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 73, 110, 115, 101, 114, 116, 72, 105, 115, 116, 111, 114, 121, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 53, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 77, 111, 100, 105, 102, 121, 72, 105, 115, 116, 111, 114, 121, 34, 32, 86, 97, 108, 117, 101, 61, 34, 53, 49, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 68, 101, 108, 101, 116, 101, 72, 105, 115, 116, 111, 114, 121, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 48, 50, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 99, 101, 105, 118, 101, 69, 118, 101, 110, 116, 115, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 48, 52, 56, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 67, 97, 108, 108, 34, 32, 86, 97, 108, 117, 101, 61, 34, 52, 48, 57, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 65, 100, 100, 82, 101, 102, 101, 114, 101, 110, 99, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 56, 49, 57, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 109, 111, 118, 101, 82, 101, 102, 101, 114, 101, 110, 99, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 54, 51, 56, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 68, 101, 108, 101, 116, 101, 78, 111, 100, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 51, 50, 55, 54, 56, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 65, 100, 100, 78, 111, 100, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 54, 53, 53, 51, 54, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 65, 99, 99, 101, 115, 115, 76, 101, 118, 101, 108, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 56, 34, 32, 73, 115, 79, 112, 116, 105, 111, 110, 83, 101, 116, 61, 34, 116, 114, 117, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 110, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 67, 117, 114, 114, 101, 110, 116, 82, 101, 97, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 67, 117, 114, 114, 101, 110, 116, 87, 114, 105, 116, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 72, 105, 115, 116, 111, 114, 121, 82, 101, 97, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 72, 105, 115, 116, 111, 114, 121, 87, 114, 105, 116, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 56, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 83, 101, 109, 97, 110, 116, 105, 99, 67, 104, 97, 110, 103, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 116, 117, 115, 87, 114, 105, 116, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 84, 105, 109, 101, 115, 116, 97, 109, 112, 87, 114, 105, 116, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 54, 52, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 65, 99, 99, 101, 115, 115, 76, 101, 118, 101, 108, 69, 120, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 32, 73, 115, 79, 112, 116, 105, 111, 110, 83, 101, 116, 61, 34, 116, 114, 117, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 110, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 67, 117, 114, 114, 101, 110, 116, 82, 101, 97, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 67, 117, 114, 114, 101, 110, 116, 87, 114, 105, 116, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 72, 105, 115, 116, 111, 114, 121, 82, 101, 97, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 72, 105, 115, 116, 111, 114, 121, 87, 114, 105, 116, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 56, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 83, 101, 109, 97, 110, 116, 105, 99, 67, 104, 97, 110, 103, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 116, 117, 115, 87, 114, 105, 116, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 84, 105, 109, 101, 115, 116, 97, 109, 112, 87, 114, 105, 116, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 54, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 110, 97, 116, 111, 109, 105, 99, 82, 101, 97, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 53, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 110, 97, 116, 111, 109, 105, 99, 87, 114, 105, 116, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 53, 49, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 70, 117, 108, 108, 65, 114, 114, 97, 121, 79, 110, 108, 121, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 48, 50, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 83, 117, 98, 68, 97, 116, 97, 84, 121, 112, 101, 115, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 48, 52, 56, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 69, 118, 101, 110, 116, 78, 111, 116, 105, 102, 105, 101, 114, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 56, 34, 32, 73, 115, 79, 112, 116, 105, 111, 110, 83, 101, 116, 61, 34, 116, 114, 117, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 110, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 83, 117, 98, 115, 99, 114, 105, 98, 101, 84, 111, 69, 118, 101, 110, 116, 115, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 72, 105, 115, 116, 111, 114, 121, 82, 101, 97, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 72, 105, 115, 116, 111, 114, 121, 87, 114, 105, 116, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 56, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 65, 99, 99, 101, 115, 115, 82, 101, 115, 116, 114, 105, 99, 116, 105, 111, 110, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 49, 54, 34, 32, 73, 115, 79, 112, 116, 105, 111, 110, 83, 101, 116, 61, 34, 116, 114, 117, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 110, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 83, 105, 103, 110, 105, 110, 103, 82, 101, 113, 117, 105, 114, 101, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 69, 110, 99, 114, 121, 112, 116, 105, 111, 110, 82, 101, 113, 117, 105, 114, 101, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 83, 101, 115, 115, 105, 111, 110, 82, 101, 113, 117, 105, 114, 101, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 65, 112, 112, 108, 121, 82, 101, 115, 116, 114, 105, 99, 116, 105, 111, 110, 115, 84, 111, 66, 114, 111, 119, 115, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 56, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 111, 108, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 116, 114, 117, 99, 116, 117, 114, 101, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 83, 116, 114, 117, 99, 116, 117, 114, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 83, 116, 114, 117, 99, 116, 117, 114, 101, 87, 105, 116, 104, 79, 112, 116, 105, 111, 110, 97, 108, 70, 105, 101, 108, 100, 115, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 85, 110, 105, 111, 110, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 116, 114, 117, 99, 116, 117, 114, 101, 70, 105, 101, 108, 100, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 86, 97, 108, 117, 101, 82, 97, 110, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 65, 114, 114, 97, 121, 68, 105, 109, 101, 110, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 114, 114, 97, 121, 68, 105, 109, 101, 110, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 65, 114, 114, 97, 121, 68, 105, 109, 101, 110, 115, 105, 111, 110, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 97, 120, 83, 116, 114, 105, 110, 103, 76, 101, 110, 103, 116, 104, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 115, 79, 112, 116, 105, 111, 110, 97, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 116, 114, 117, 99, 116, 117, 114, 101, 68, 101, 102, 105, 110, 105, 116, 105, 111, 110, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 68, 97, 116, 97, 84, 121, 112, 101, 68, 101, 102, 105, 110, 105, 116, 105, 111, 110, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 102, 97, 117, 108, 116, 69, 110, 99, 111, 100, 105, 110, 103, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 97, 115, 101, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 116, 114, 117, 99, 116, 117, 114, 101, 84, 121, 112, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 70, 105, 101, 108, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 70, 105, 101, 108, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 70, 105, 101, 108, 100, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 70, 105, 101, 108, 100, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 69, 110, 117, 109, 68, 101, 102, 105, 110, 105, 116, 105, 111, 110, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 68, 97, 116, 97, 84, 121, 112, 101, 68, 101, 102, 105, 110, 105, 116, 105, 111, 110, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 70, 105, 101, 108, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 70, 105, 101, 108, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 69, 110, 117, 109, 70, 105, 101, 108, 100, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 70, 105, 101, 108, 100, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 67, 108, 97, 115, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 67, 108, 97, 115, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 119, 115, 101, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 81, 117, 97, 108, 105, 102, 105, 101, 100, 78, 97, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 112, 108, 97, 121, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 85, 115, 101, 114, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 85, 115, 101, 114, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 99, 99, 101, 115, 115, 82, 101, 115, 116, 114, 105, 99, 116, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 102, 101, 114, 101, 110, 99, 101, 78, 111, 100, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 73, 110, 115, 116, 97, 110, 99, 101, 78, 111, 100, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 67, 108, 97, 115, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 67, 108, 97, 115, 115, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 119, 115, 101, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 81, 117, 97, 108, 105, 102, 105, 101, 100, 78, 97, 109, 101, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 112, 108, 97, 121, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 85, 115, 101, 114, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 85, 115, 101, 114, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 99, 99, 101, 115, 115, 82, 101, 115, 116, 114, 105, 99, 116, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 49, 54, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 102, 101, 114, 101, 110, 99, 101, 78, 111, 100, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 84, 121, 112, 101, 78, 111, 100, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 67, 108, 97, 115, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 67, 108, 97, 115, 115, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 119, 115, 101, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 81, 117, 97, 108, 105, 102, 105, 101, 100, 78, 97, 109, 101, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 112, 108, 97, 121, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 85, 115, 101, 114, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 85, 115, 101, 114, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 99, 99, 101, 115, 115, 82, 101, 115, 116, 114, 105, 99, 116, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 49, 54, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 102, 101, 114, 101, 110, 99, 101, 78, 111, 100, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 79, 98, 106, 101, 99, 116, 78, 111, 100, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 73, 110, 115, 116, 97, 110, 99, 101, 78, 111, 100, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 67, 108, 97, 115, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 67, 108, 97, 115, 115, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 119, 115, 101, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 81, 117, 97, 108, 105, 102, 105, 101, 100, 78, 97, 109, 101, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 112, 108, 97, 121, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 85, 115, 101, 114, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 85, 115, 101, 114, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 99, 99, 101, 115, 115, 82, 101, 115, 116, 114, 105, 99, 116, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 49, 54, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 102, 101, 114, 101, 110, 99, 101, 78, 111, 100, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 118, 101, 110, 116, 78, 111, 116, 105, 102, 105, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 79, 98, 106, 101, 99, 116, 84, 121, 112, 101, 78, 111, 100, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 84, 121, 112, 101, 78, 111, 100, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 67, 108, 97, 115, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 67, 108, 97, 115, 115, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 119, 115, 101, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 81, 117, 97, 108, 105, 102, 105, 101, 100, 78, 97, 109, 101, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 112, 108, 97, 121, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 85, 115, 101, 114, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 85, 115, 101, 114, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 99, 99, 101, 115, 115, 82, 101, 115, 116, 114, 105, 99, 116, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 49, 54, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 102, 101, 114, 101, 110, 99, 101, 78, 111, 100, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 115, 65, 98, 115, 116, 114, 97, 99, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 86, 97, 114, 105, 97, 98, 108, 101, 78, 111, 100, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 73, 110, 115, 116, 97, 110, 99, 101, 78, 111, 100, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 67, 108, 97, 115, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 67, 108, 97, 115, 115, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 119, 115, 101, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 81, 117, 97, 108, 105, 102, 105, 101, 100, 78, 97, 109, 101, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 112, 108, 97, 121, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 85, 115, 101, 114, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 85, 115, 101, 114, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 99, 99, 101, 115, 115, 82, 101, 115, 116, 114, 105, 99, 116, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 49, 54, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 102, 101, 114, 101, 110, 99, 101, 78, 111, 100, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 86, 97, 108, 117, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 86, 97, 114, 105, 97, 110, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 86, 97, 108, 117, 101, 82, 97, 110, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 65, 114, 114, 97, 121, 68, 105, 109, 101, 110, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 114, 114, 97, 121, 68, 105, 109, 101, 110, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 65, 114, 114, 97, 121, 68, 105, 109, 101, 110, 115, 105, 111, 110, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 99, 99, 101, 115, 115, 76, 101, 118, 101, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 65, 99, 99, 101, 115, 115, 76, 101, 118, 101, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 105, 110, 105, 109, 117, 109, 83, 97, 109, 112, 108, 105, 110, 103, 73, 110, 116, 101, 114, 118, 97, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 72, 105, 115, 116, 111, 114, 105, 122, 105, 110, 103, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 99, 99, 101, 115, 115, 76, 101, 118, 101, 108, 69, 120, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 86, 97, 114, 105, 97, 98, 108, 101, 84, 121, 112, 101, 78, 111, 100, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 84, 121, 112, 101, 78, 111, 100, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 67, 108, 97, 115, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 67, 108, 97, 115, 115, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 119, 115, 101, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 81, 117, 97, 108, 105, 102, 105, 101, 100, 78, 97, 109, 101, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 112, 108, 97, 121, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 85, 115, 101, 114, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 85, 115, 101, 114, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 99, 99, 101, 115, 115, 82, 101, 115, 116, 114, 105, 99, 116, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 49, 54, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 102, 101, 114, 101, 110, 99, 101, 78, 111, 100, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 86, 97, 108, 117, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 86, 97, 114, 105, 97, 110, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 86, 97, 108, 117, 101, 82, 97, 110, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 65, 114, 114, 97, 121, 68, 105, 109, 101, 110, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 114, 114, 97, 121, 68, 105, 109, 101, 110, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 65, 114, 114, 97, 121, 68, 105, 109, 101, 110, 115, 105, 111, 110, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 115, 65, 98, 115, 116, 114, 97, 99, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 102, 101, 114, 101, 110, 99, 101, 84, 121, 112, 101, 78, 111, 100, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 84, 121, 112, 101, 78, 111, 100, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 67, 108, 97, 115, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 67, 108, 97, 115, 115, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 119, 115, 101, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 81, 117, 97, 108, 105, 102, 105, 101, 100, 78, 97, 109, 101, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 112, 108, 97, 121, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 85, 115, 101, 114, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 85, 115, 101, 114, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 99, 99, 101, 115, 115, 82, 101, 115, 116, 114, 105, 99, 116, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 49, 54, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 102, 101, 114, 101, 110, 99, 101, 78, 111, 100, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 115, 65, 98, 115, 116, 114, 97, 99, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 121, 109, 109, 101, 116, 114, 105, 99, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 110, 118, 101, 114, 115, 101, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 77, 101, 116, 104, 111, 100, 78, 111, 100, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 73, 110, 115, 116, 97, 110, 99, 101, 78, 111, 100, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 67, 108, 97, 115, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 67, 108, 97, 115, 115, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 119, 115, 101, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 81, 117, 97, 108, 105, 102, 105, 101, 100, 78, 97, 109, 101, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 112, 108, 97, 121, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 85, 115, 101, 114, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 85, 115, 101, 114, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 99, 99, 101, 115, 115, 82, 101, 115, 116, 114, 105, 99, 116, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 49, 54, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 102, 101, 114, 101, 110, 99, 101, 78, 111, 100, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 120, 101, 99, 117, 116, 97, 98, 108, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 69, 120, 101, 99, 117, 116, 97, 98, 108, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 86, 105, 101, 119, 78, 111, 100, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 73, 110, 115, 116, 97, 110, 99, 101, 78, 111, 100, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 67, 108, 97, 115, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 67, 108, 97, 115, 115, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 119, 115, 101, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 81, 117, 97, 108, 105, 102, 105, 101, 100, 78, 97, 109, 101, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 112, 108, 97, 121, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 85, 115, 101, 114, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 85, 115, 101, 114, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 99, 99, 101, 115, 115, 82, 101, 115, 116, 114, 105, 99, 116, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 49, 54, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 102, 101, 114, 101, 110, 99, 101, 78, 111, 100, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 111, 110, 116, 97, 105, 110, 115, 78, 111, 76, 111, 111, 112, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 118, 101, 110, 116, 78, 111, 116, 105, 102, 105, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 84, 121, 112, 101, 78, 111, 100, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 84, 121, 112, 101, 78, 111, 100, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 67, 108, 97, 115, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 67, 108, 97, 115, 115, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 119, 115, 101, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 81, 117, 97, 108, 105, 102, 105, 101, 100, 78, 97, 109, 101, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 112, 108, 97, 121, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 85, 115, 101, 114, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 85, 115, 101, 114, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 99, 99, 101, 115, 115, 82, 101, 115, 116, 114, 105, 99, 116, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 49, 54, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 102, 101, 114, 101, 110, 99, 101, 78, 111, 100, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 115, 65, 98, 115, 116, 114, 97, 99, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 84, 121, 112, 101, 68, 101, 102, 105, 110, 105, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 102, 101, 114, 101, 110, 99, 101, 78, 111, 100, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 102, 101, 114, 101, 110, 99, 101, 84, 121, 112, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 115, 73, 110, 118, 101, 114, 115, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 97, 114, 103, 101, 116, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 112, 97, 110, 100, 101, 100, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 65, 114, 103, 117, 109, 101, 110, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 86, 97, 108, 117, 101, 82, 97, 110, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 65, 114, 114, 97, 121, 68, 105, 109, 101, 110, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 114, 114, 97, 121, 68, 105, 109, 101, 110, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 65, 114, 114, 97, 121, 68, 105, 109, 101, 110, 115, 105, 111, 110, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 69, 110, 117, 109, 86, 97, 108, 117, 101, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 86, 97, 108, 117, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 54, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 112, 108, 97, 121, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 69, 110, 117, 109, 70, 105, 101, 108, 100, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 69, 110, 117, 109, 86, 97, 108, 117, 101, 84, 121, 112, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 86, 97, 108, 117, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 54, 52, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 69, 110, 117, 109, 86, 97, 108, 117, 101, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 112, 108, 97, 121, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 69, 110, 117, 109, 86, 97, 108, 117, 101, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 69, 110, 117, 109, 86, 97, 108, 117, 101, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 79, 112, 116, 105, 111, 110, 83, 101, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 86, 97, 108, 117, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 86, 97, 108, 105, 100, 66, 105, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 85, 110, 105, 111, 110, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 114, 109, 97, 108, 105, 122, 101, 100, 83, 116, 114, 105, 110, 103, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 101, 99, 105, 109, 97, 108, 83, 116, 114, 105, 110, 103, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 117, 114, 97, 116, 105, 111, 110, 83, 116, 114, 105, 110, 103, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 84, 105, 109, 101, 83, 116, 114, 105, 110, 103, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 101, 83, 116, 114, 105, 110, 103, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 117, 114, 97, 116, 105, 111, 110, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 85, 116, 99, 84, 105, 109, 101, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 76, 111, 99, 97, 108, 101, 73, 100, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 84, 105, 109, 101, 90, 111, 110, 101, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 79, 102, 102, 115, 101, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 121, 108, 105, 103, 104, 116, 83, 97, 118, 105, 110, 103, 73, 110, 79, 102, 102, 115, 101, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 73, 110, 100, 101, 120, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 73, 110, 116, 101, 103, 101, 114, 73, 100, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 65, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 67, 108, 105, 101, 110, 116, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 67, 108, 105, 101, 110, 116, 65, 110, 100, 83, 101, 114, 118, 101, 114, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 99, 111, 118, 101, 114, 121, 83, 101, 114, 118, 101, 114, 34, 32, 86, 97, 108, 117, 101, 61, 34, 51, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 65, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 85, 114, 105, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 114, 111, 100, 117, 99, 116, 85, 114, 105, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 84, 121, 112, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 65, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 71, 97, 116, 101, 119, 97, 121, 83, 101, 114, 118, 101, 114, 85, 114, 105, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 99, 111, 118, 101, 114, 121, 80, 114, 111, 102, 105, 108, 101, 85, 114, 105, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 105, 115, 99, 111, 118, 101, 114, 121, 85, 114, 108, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 99, 111, 118, 101, 114, 121, 85, 114, 108, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 105, 115, 99, 111, 118, 101, 114, 121, 85, 114, 108, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 117, 116, 104, 101, 110, 116, 105, 99, 97, 116, 105, 111, 110, 84, 111, 107, 101, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 105, 109, 101, 115, 116, 97, 109, 112, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 97, 110, 100, 108, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 116, 117, 114, 110, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 117, 100, 105, 116, 69, 110, 116, 114, 121, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 105, 109, 101, 111, 117, 116, 72, 105, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 100, 100, 105, 116, 105, 111, 110, 97, 108, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 105, 109, 101, 115, 116, 97, 109, 112, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 97, 110, 100, 108, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 105, 99, 101, 82, 101, 115, 117, 108, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 105, 99, 101, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 83, 116, 114, 105, 110, 103, 84, 97, 98, 108, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 116, 114, 105, 110, 103, 84, 97, 98, 108, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 83, 116, 114, 105, 110, 103, 84, 97, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 100, 100, 105, 116, 105, 111, 110, 97, 108, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 86, 101, 114, 115, 105, 111, 110, 84, 105, 109, 101, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 105, 99, 101, 70, 97, 117, 108, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 101, 115, 115, 105, 111, 110, 108, 101, 115, 115, 73, 110, 118, 111, 107, 101, 82, 101, 113, 117, 101, 115, 116, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 114, 105, 115, 86, 101, 114, 115, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 78, 97, 109, 101, 115, 112, 97, 99, 101, 85, 114, 105, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 101, 115, 112, 97, 99, 101, 85, 114, 105, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 78, 97, 109, 101, 115, 112, 97, 99, 101, 85, 114, 105, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 83, 101, 114, 118, 101, 114, 85, 114, 105, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 85, 114, 105, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 83, 101, 114, 118, 101, 114, 85, 114, 105, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 76, 111, 99, 97, 108, 101, 73, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 76, 111, 99, 97, 108, 101, 73, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 76, 111, 99, 97, 108, 101, 73, 100, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 105, 99, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 101, 115, 115, 105, 111, 110, 108, 101, 115, 115, 73, 110, 118, 111, 107, 101, 82, 101, 115, 112, 111, 110, 115, 101, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 78, 97, 109, 101, 115, 112, 97, 99, 101, 85, 114, 105, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 101, 115, 112, 97, 99, 101, 85, 114, 105, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 78, 97, 109, 101, 115, 112, 97, 99, 101, 85, 114, 105, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 83, 101, 114, 118, 101, 114, 85, 114, 105, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 85, 114, 105, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 83, 101, 114, 118, 101, 114, 85, 114, 105, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 105, 99, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 70, 105, 110, 100, 83, 101, 114, 118, 101, 114, 115, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 110, 100, 112, 111, 105, 110, 116, 85, 114, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 76, 111, 99, 97, 108, 101, 73, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 76, 111, 99, 97, 108, 101, 73, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 76, 111, 99, 97, 108, 101, 73, 100, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 83, 101, 114, 118, 101, 114, 85, 114, 105, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 85, 114, 105, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 83, 101, 114, 118, 101, 114, 85, 114, 105, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 70, 105, 110, 100, 83, 101, 114, 118, 101, 114, 115, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 83, 101, 114, 118, 101, 114, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 65, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 83, 101, 114, 118, 101, 114, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 79, 110, 78, 101, 116, 119, 111, 114, 107, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 99, 111, 114, 100, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 99, 111, 118, 101, 114, 121, 85, 114, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 83, 101, 114, 118, 101, 114, 67, 97, 112, 97, 98, 105, 108, 105, 116, 105, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 67, 97, 112, 97, 98, 105, 108, 105, 116, 105, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 83, 101, 114, 118, 101, 114, 67, 97, 112, 97, 98, 105, 108, 105, 116, 105, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 70, 105, 110, 100, 83, 101, 114, 118, 101, 114, 115, 79, 110, 78, 101, 116, 119, 111, 114, 107, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 114, 116, 105, 110, 103, 82, 101, 99, 111, 114, 100, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 97, 120, 82, 101, 99, 111, 114, 100, 115, 84, 111, 82, 101, 116, 117, 114, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 83, 101, 114, 118, 101, 114, 67, 97, 112, 97, 98, 105, 108, 105, 116, 121, 70, 105, 108, 116, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 67, 97, 112, 97, 98, 105, 108, 105, 116, 121, 70, 105, 108, 116, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 83, 101, 114, 118, 101, 114, 67, 97, 112, 97, 98, 105, 108, 105, 116, 121, 70, 105, 108, 116, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 70, 105, 110, 100, 83, 101, 114, 118, 101, 114, 115, 79, 110, 78, 101, 116, 119, 111, 114, 107, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 76, 97, 115, 116, 67, 111, 117, 110, 116, 101, 114, 82, 101, 115, 101, 116, 84, 105, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 83, 101, 114, 118, 101, 114, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 101, 114, 118, 101, 114, 79, 110, 78, 101, 116, 119, 111, 114, 107, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 83, 101, 114, 118, 101, 114, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 65, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 73, 110, 115, 116, 97, 110, 99, 101, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 77, 101, 115, 115, 97, 103, 101, 83, 101, 99, 117, 114, 105, 116, 121, 77, 111, 100, 101, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 73, 110, 118, 97, 108, 105, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 110, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 83, 105, 103, 110, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 83, 105, 103, 110, 65, 110, 100, 69, 110, 99, 114, 121, 112, 116, 34, 32, 86, 97, 108, 117, 101, 61, 34, 51, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 84, 111, 107, 101, 110, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 65, 110, 111, 110, 121, 109, 111, 117, 115, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 78, 97, 109, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 73, 115, 115, 117, 101, 100, 84, 111, 107, 101, 110, 34, 32, 86, 97, 108, 117, 101, 61, 34, 51, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 84, 111, 107, 101, 110, 80, 111, 108, 105, 99, 121, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 111, 108, 105, 99, 121, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 111, 107, 101, 110, 84, 121, 112, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 85, 115, 101, 114, 84, 111, 107, 101, 110, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 115, 115, 117, 101, 100, 84, 111, 107, 101, 110, 84, 121, 112, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 115, 115, 117, 101, 114, 69, 110, 100, 112, 111, 105, 110, 116, 85, 114, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 99, 117, 114, 105, 116, 121, 80, 111, 108, 105, 99, 121, 85, 114, 105, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 69, 110, 100, 112, 111, 105, 110, 116, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 110, 100, 112, 111, 105, 110, 116, 85, 114, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 65, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 99, 117, 114, 105, 116, 121, 77, 111, 100, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 77, 101, 115, 115, 97, 103, 101, 83, 101, 99, 117, 114, 105, 116, 121, 77, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 99, 117, 114, 105, 116, 121, 80, 111, 108, 105, 99, 121, 85, 114, 105, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 85, 115, 101, 114, 73, 100, 101, 110, 116, 105, 116, 121, 84, 111, 107, 101, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 73, 100, 101, 110, 116, 105, 116, 121, 84, 111, 107, 101, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 85, 115, 101, 114, 84, 111, 107, 101, 110, 80, 111, 108, 105, 99, 121, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 85, 115, 101, 114, 73, 100, 101, 110, 116, 105, 116, 121, 84, 111, 107, 101, 110, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 114, 97, 110, 115, 112, 111, 114, 116, 80, 114, 111, 102, 105, 108, 101, 85, 114, 105, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 99, 117, 114, 105, 116, 121, 76, 101, 118, 101, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 71, 101, 116, 69, 110, 100, 112, 111, 105, 110, 116, 115, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 110, 100, 112, 111, 105, 110, 116, 85, 114, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 76, 111, 99, 97, 108, 101, 73, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 76, 111, 99, 97, 108, 101, 73, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 76, 111, 99, 97, 108, 101, 73, 100, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 80, 114, 111, 102, 105, 108, 101, 85, 114, 105, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 114, 111, 102, 105, 108, 101, 85, 114, 105, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 80, 114, 111, 102, 105, 108, 101, 85, 114, 105, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 71, 101, 116, 69, 110, 100, 112, 111, 105, 110, 116, 115, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 69, 110, 100, 112, 111, 105, 110, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 110, 100, 112, 111, 105, 110, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 69, 110, 100, 112, 111, 105, 110, 116, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 69, 110, 100, 112, 111, 105, 110, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 103, 105, 115, 116, 101, 114, 101, 100, 83, 101, 114, 118, 101, 114, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 85, 114, 105, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 114, 111, 100, 117, 99, 116, 85, 114, 105, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 83, 101, 114, 118, 101, 114, 78, 97, 109, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 78, 97, 109, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 83, 101, 114, 118, 101, 114, 78, 97, 109, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 84, 121, 112, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 65, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 71, 97, 116, 101, 119, 97, 121, 83, 101, 114, 118, 101, 114, 85, 114, 105, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 105, 115, 99, 111, 118, 101, 114, 121, 85, 114, 108, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 99, 111, 118, 101, 114, 121, 85, 114, 108, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 105, 115, 99, 111, 118, 101, 114, 121, 85, 114, 108, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 109, 97, 112, 104, 111, 114, 101, 70, 105, 108, 101, 80, 97, 116, 104, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 115, 79, 110, 108, 105, 110, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 103, 105, 115, 116, 101, 114, 83, 101, 114, 118, 101, 114, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 103, 105, 115, 116, 101, 114, 101, 100, 83, 101, 114, 118, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 103, 105, 115, 116, 101, 114, 83, 101, 114, 118, 101, 114, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 99, 111, 118, 101, 114, 121, 67, 111, 110, 102, 105, 103, 117, 114, 97, 116, 105, 111, 110, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 77, 100, 110, 115, 68, 105, 115, 99, 111, 118, 101, 114, 121, 67, 111, 110, 102, 105, 103, 117, 114, 97, 116, 105, 111, 110, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 68, 105, 115, 99, 111, 118, 101, 114, 121, 67, 111, 110, 102, 105, 103, 117, 114, 97, 116, 105, 111, 110, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 100, 110, 115, 83, 101, 114, 118, 101, 114, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 83, 101, 114, 118, 101, 114, 67, 97, 112, 97, 98, 105, 108, 105, 116, 105, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 67, 97, 112, 97, 98, 105, 108, 105, 116, 105, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 83, 101, 114, 118, 101, 114, 67, 97, 112, 97, 98, 105, 108, 105, 116, 105, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 103, 105, 115, 116, 101, 114, 83, 101, 114, 118, 101, 114, 50, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 103, 105, 115, 116, 101, 114, 101, 100, 83, 101, 114, 118, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 105, 115, 99, 111, 118, 101, 114, 121, 67, 111, 110, 102, 105, 103, 117, 114, 97, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 99, 111, 118, 101, 114, 121, 67, 111, 110, 102, 105, 103, 117, 114, 97, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 105, 115, 99, 111, 118, 101, 114, 121, 67, 111, 110, 102, 105, 103, 117, 114, 97, 116, 105, 111, 110, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 103, 105, 115, 116, 101, 114, 83, 101, 114, 118, 101, 114, 50, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 67, 111, 110, 102, 105, 103, 117, 114, 97, 116, 105, 111, 110, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 111, 110, 102, 105, 103, 117, 114, 97, 116, 105, 111, 110, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 67, 111, 110, 102, 105, 103, 117, 114, 97, 116, 105, 111, 110, 82, 101, 115, 117, 108, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 101, 99, 117, 114, 105, 116, 121, 84, 111, 107, 101, 110, 82, 101, 113, 117, 101, 115, 116, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 73, 115, 115, 117, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 110, 101, 119, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 67, 104, 97, 110, 110, 101, 108, 83, 101, 99, 117, 114, 105, 116, 121, 84, 111, 107, 101, 110, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 104, 97, 110, 110, 101, 108, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 111, 107, 101, 110, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 114, 101, 97, 116, 101, 100, 65, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 118, 105, 115, 101, 100, 76, 105, 102, 101, 116, 105, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 79, 112, 101, 110, 83, 101, 99, 117, 114, 101, 67, 104, 97, 110, 110, 101, 108, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 108, 105, 101, 110, 116, 80, 114, 111, 116, 111, 99, 111, 108, 86, 101, 114, 115, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 84, 121, 112, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 101, 99, 117, 114, 105, 116, 121, 84, 111, 107, 101, 110, 82, 101, 113, 117, 101, 115, 116, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 99, 117, 114, 105, 116, 121, 77, 111, 100, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 77, 101, 115, 115, 97, 103, 101, 83, 101, 99, 117, 114, 105, 116, 121, 77, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 108, 105, 101, 110, 116, 78, 111, 110, 99, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 101, 100, 76, 105, 102, 101, 116, 105, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 79, 112, 101, 110, 83, 101, 99, 117, 114, 101, 67, 104, 97, 110, 110, 101, 108, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 80, 114, 111, 116, 111, 99, 111, 108, 86, 101, 114, 115, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 99, 117, 114, 105, 116, 121, 84, 111, 107, 101, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 67, 104, 97, 110, 110, 101, 108, 83, 101, 99, 117, 114, 105, 116, 121, 84, 111, 107, 101, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 78, 111, 110, 99, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 67, 108, 111, 115, 101, 83, 101, 99, 117, 114, 101, 67, 104, 97, 110, 110, 101, 108, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 67, 108, 111, 115, 101, 83, 101, 99, 117, 114, 101, 67, 104, 97, 110, 110, 101, 108, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 105, 103, 110, 101, 100, 83, 111, 102, 116, 119, 97, 114, 101, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 68, 97, 116, 97, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 105, 103, 110, 97, 116, 117, 114, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 101, 115, 115, 105, 111, 110, 65, 117, 116, 104, 101, 110, 116, 105, 99, 97, 116, 105, 111, 110, 84, 111, 107, 101, 110, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 105, 103, 110, 97, 116, 117, 114, 101, 68, 97, 116, 97, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 108, 103, 111, 114, 105, 116, 104, 109, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 105, 103, 110, 97, 116, 117, 114, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 67, 114, 101, 97, 116, 101, 83, 101, 115, 115, 105, 111, 110, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 108, 105, 101, 110, 116, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 65, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 85, 114, 105, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 110, 100, 112, 111, 105, 110, 116, 85, 114, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 115, 115, 105, 111, 110, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 108, 105, 101, 110, 116, 78, 111, 110, 99, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 108, 105, 101, 110, 116, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 101, 100, 83, 101, 115, 115, 105, 111, 110, 84, 105, 109, 101, 111, 117, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 97, 120, 82, 101, 115, 112, 111, 110, 115, 101, 77, 101, 115, 115, 97, 103, 101, 83, 105, 122, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 67, 114, 101, 97, 116, 101, 83, 101, 115, 115, 105, 111, 110, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 115, 115, 105, 111, 110, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 117, 116, 104, 101, 110, 116, 105, 99, 97, 116, 105, 111, 110, 84, 111, 107, 101, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 118, 105, 115, 101, 100, 83, 101, 115, 115, 105, 111, 110, 84, 105, 109, 101, 111, 117, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 78, 111, 110, 99, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 83, 101, 114, 118, 101, 114, 69, 110, 100, 112, 111, 105, 110, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 69, 110, 100, 112, 111, 105, 110, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 69, 110, 100, 112, 111, 105, 110, 116, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 83, 101, 114, 118, 101, 114, 69, 110, 100, 112, 111, 105, 110, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 83, 101, 114, 118, 101, 114, 83, 111, 102, 116, 119, 97, 114, 101, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 83, 111, 102, 116, 119, 97, 114, 101, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 105, 103, 110, 101, 100, 83, 111, 102, 116, 119, 97, 114, 101, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 83, 101, 114, 118, 101, 114, 83, 111, 102, 116, 119, 97, 114, 101, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 83, 105, 103, 110, 97, 116, 117, 114, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 105, 103, 110, 97, 116, 117, 114, 101, 68, 97, 116, 97, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 97, 120, 82, 101, 113, 117, 101, 115, 116, 77, 101, 115, 115, 97, 103, 101, 83, 105, 122, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 73, 100, 101, 110, 116, 105, 116, 121, 84, 111, 107, 101, 110, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 111, 108, 105, 99, 121, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 65, 110, 111, 110, 121, 109, 111, 117, 115, 73, 100, 101, 110, 116, 105, 116, 121, 84, 111, 107, 101, 110, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 85, 115, 101, 114, 73, 100, 101, 110, 116, 105, 116, 121, 84, 111, 107, 101, 110, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 111, 108, 105, 99, 121, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 85, 115, 101, 114, 73, 100, 101, 110, 116, 105, 116, 121, 84, 111, 107, 101, 110, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 78, 97, 109, 101, 73, 100, 101, 110, 116, 105, 116, 121, 84, 111, 107, 101, 110, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 85, 115, 101, 114, 73, 100, 101, 110, 116, 105, 116, 121, 84, 111, 107, 101, 110, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 111, 108, 105, 99, 121, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 85, 115, 101, 114, 73, 100, 101, 110, 116, 105, 116, 121, 84, 111, 107, 101, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 97, 115, 115, 119, 111, 114, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 110, 99, 114, 121, 112, 116, 105, 111, 110, 65, 108, 103, 111, 114, 105, 116, 104, 109, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 88, 53, 48, 57, 73, 100, 101, 110, 116, 105, 116, 121, 84, 111, 107, 101, 110, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 85, 115, 101, 114, 73, 100, 101, 110, 116, 105, 116, 121, 84, 111, 107, 101, 110, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 111, 108, 105, 99, 121, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 85, 115, 101, 114, 73, 100, 101, 110, 116, 105, 116, 121, 84, 111, 107, 101, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 68, 97, 116, 97, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 73, 115, 115, 117, 101, 100, 73, 100, 101, 110, 116, 105, 116, 121, 84, 111, 107, 101, 110, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 85, 115, 101, 114, 73, 100, 101, 110, 116, 105, 116, 121, 84, 111, 107, 101, 110, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 111, 108, 105, 99, 121, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 85, 115, 101, 114, 73, 100, 101, 110, 116, 105, 116, 121, 84, 111, 107, 101, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 111, 107, 101, 110, 68, 97, 116, 97, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 110, 99, 114, 121, 112, 116, 105, 111, 110, 65, 108, 103, 111, 114, 105, 116, 104, 109, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 82, 115, 97, 69, 110, 99, 114, 121, 112, 116, 101, 100, 83, 101, 99, 114, 101, 116, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 69, 99, 99, 69, 110, 99, 114, 121, 112, 116, 101, 100, 83, 101, 99, 114, 101, 116, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 65, 99, 116, 105, 118, 97, 116, 101, 83, 101, 115, 115, 105, 111, 110, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 108, 105, 101, 110, 116, 83, 105, 103, 110, 97, 116, 117, 114, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 105, 103, 110, 97, 116, 117, 114, 101, 68, 97, 116, 97, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 67, 108, 105, 101, 110, 116, 83, 111, 102, 116, 119, 97, 114, 101, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 108, 105, 101, 110, 116, 83, 111, 102, 116, 119, 97, 114, 101, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 105, 103, 110, 101, 100, 83, 111, 102, 116, 119, 97, 114, 101, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 67, 108, 105, 101, 110, 116, 83, 111, 102, 116, 119, 97, 114, 101, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 76, 111, 99, 97, 108, 101, 73, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 76, 111, 99, 97, 108, 101, 73, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 76, 111, 99, 97, 108, 101, 73, 100, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 73, 100, 101, 110, 116, 105, 116, 121, 84, 111, 107, 101, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 84, 111, 107, 101, 110, 83, 105, 103, 110, 97, 116, 117, 114, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 105, 103, 110, 97, 116, 117, 114, 101, 68, 97, 116, 97, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 65, 99, 116, 105, 118, 97, 116, 101, 83, 101, 115, 115, 105, 111, 110, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 78, 111, 110, 99, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 67, 108, 111, 115, 101, 83, 101, 115, 115, 105, 111, 110, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 108, 101, 116, 101, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 67, 108, 111, 115, 101, 83, 101, 115, 115, 105, 111, 110, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 67, 97, 110, 99, 101, 108, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 97, 110, 100, 108, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 67, 97, 110, 99, 101, 108, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 97, 110, 99, 101, 108, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 77, 97, 115, 107, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 110, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 65, 99, 99, 101, 115, 115, 76, 101, 118, 101, 108, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 65, 114, 114, 97, 121, 68, 105, 109, 101, 110, 115, 105, 111, 110, 115, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 119, 115, 101, 78, 97, 109, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 67, 111, 110, 116, 97, 105, 110, 115, 78, 111, 76, 111, 111, 112, 115, 34, 32, 86, 97, 108, 117, 101, 61, 34, 56, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 86, 97, 108, 117, 101, 61, 34, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 112, 108, 97, 121, 78, 97, 109, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 54, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 69, 118, 101, 110, 116, 78, 111, 116, 105, 102, 105, 101, 114, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 50, 56, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 69, 120, 101, 99, 117, 116, 97, 98, 108, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 53, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 72, 105, 115, 116, 111, 114, 105, 122, 105, 110, 103, 34, 32, 86, 97, 108, 117, 101, 61, 34, 53, 49, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 73, 110, 118, 101, 114, 115, 101, 78, 97, 109, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 48, 50, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 73, 115, 65, 98, 115, 116, 114, 97, 99, 116, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 48, 52, 56, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 77, 105, 110, 105, 109, 117, 109, 83, 97, 109, 112, 108, 105, 110, 103, 73, 110, 116, 101, 114, 118, 97, 108, 34, 32, 86, 97, 108, 117, 101, 61, 34, 52, 48, 57, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 67, 108, 97, 115, 115, 34, 32, 86, 97, 108, 117, 101, 61, 34, 56, 49, 57, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 73, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 54, 51, 56, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 83, 121, 109, 109, 101, 116, 114, 105, 99, 34, 32, 86, 97, 108, 117, 101, 61, 34, 51, 50, 55, 54, 56, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 65, 99, 99, 101, 115, 115, 76, 101, 118, 101, 108, 34, 32, 86, 97, 108, 117, 101, 61, 34, 54, 53, 53, 51, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 69, 120, 101, 99, 117, 116, 97, 98, 108, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 51, 49, 48, 55, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 54, 50, 49, 52, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 86, 97, 108, 117, 101, 82, 97, 110, 107, 34, 32, 86, 97, 108, 117, 101, 61, 34, 53, 50, 52, 50, 56, 56, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 48, 52, 56, 53, 55, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 86, 97, 108, 117, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 48, 57, 55, 49, 53, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 84, 121, 112, 101, 68, 101, 102, 105, 110, 105, 116, 105, 111, 110, 34, 32, 86, 97, 108, 117, 101, 61, 34, 52, 49, 57, 52, 51, 48, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 86, 97, 108, 117, 101, 61, 34, 56, 51, 56, 56, 54, 48, 56, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 65, 99, 99, 101, 115, 115, 82, 101, 115, 116, 114, 105, 99, 116, 105, 111, 110, 115, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 54, 55, 55, 55, 50, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 65, 108, 108, 34, 32, 86, 97, 108, 117, 101, 61, 34, 51, 51, 53, 53, 52, 52, 51, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 66, 97, 115, 101, 78, 111, 100, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 54, 53, 48, 49, 50, 50, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 79, 98, 106, 101, 99, 116, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 54, 53, 48, 49, 51, 52, 56, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 79, 98, 106, 101, 99, 116, 84, 121, 112, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 54, 53, 48, 51, 50, 54, 56, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 86, 97, 114, 105, 97, 98, 108, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 54, 53, 55, 49, 51, 56, 51, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 86, 97, 114, 105, 97, 98, 108, 101, 84, 121, 112, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 56, 54, 48, 48, 52, 51, 56, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 77, 101, 116, 104, 111, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 54, 54, 51, 50, 53, 52, 56, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 102, 101, 114, 101, 110, 99, 101, 84, 121, 112, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 54, 53, 51, 55, 48, 54, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 86, 105, 101, 119, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 54, 53, 48, 49, 51, 53, 54, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 112, 101, 99, 105, 102, 105, 101, 100, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 112, 108, 97, 121, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 79, 98, 106, 101, 99, 116, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 112, 101, 99, 105, 102, 105, 101, 100, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 112, 108, 97, 121, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 118, 101, 110, 116, 78, 111, 116, 105, 102, 105, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 86, 97, 114, 105, 97, 98, 108, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 112, 101, 99, 105, 102, 105, 101, 100, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 112, 108, 97, 121, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 86, 97, 108, 117, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 86, 97, 114, 105, 97, 110, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 86, 97, 108, 117, 101, 82, 97, 110, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 65, 114, 114, 97, 121, 68, 105, 109, 101, 110, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 114, 114, 97, 121, 68, 105, 109, 101, 110, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 65, 114, 114, 97, 121, 68, 105, 109, 101, 110, 115, 105, 111, 110, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 99, 99, 101, 115, 115, 76, 101, 118, 101, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 65, 99, 99, 101, 115, 115, 76, 101, 118, 101, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 105, 110, 105, 109, 117, 109, 83, 97, 109, 112, 108, 105, 110, 103, 73, 110, 116, 101, 114, 118, 97, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 72, 105, 115, 116, 111, 114, 105, 122, 105, 110, 103, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 77, 101, 116, 104, 111, 100, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 112, 101, 99, 105, 102, 105, 101, 100, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 112, 108, 97, 121, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 120, 101, 99, 117, 116, 97, 98, 108, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 69, 120, 101, 99, 117, 116, 97, 98, 108, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 79, 98, 106, 101, 99, 116, 84, 121, 112, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 112, 101, 99, 105, 102, 105, 101, 100, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 112, 108, 97, 121, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 115, 65, 98, 115, 116, 114, 97, 99, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 86, 97, 114, 105, 97, 98, 108, 101, 84, 121, 112, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 112, 101, 99, 105, 102, 105, 101, 100, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 112, 108, 97, 121, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 86, 97, 108, 117, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 86, 97, 114, 105, 97, 110, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 86, 97, 108, 117, 101, 82, 97, 110, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 65, 114, 114, 97, 121, 68, 105, 109, 101, 110, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 114, 114, 97, 121, 68, 105, 109, 101, 110, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 65, 114, 114, 97, 121, 68, 105, 109, 101, 110, 115, 105, 111, 110, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 115, 65, 98, 115, 116, 114, 97, 99, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 102, 101, 114, 101, 110, 99, 101, 84, 121, 112, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 112, 101, 99, 105, 102, 105, 101, 100, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 112, 108, 97, 121, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 115, 65, 98, 115, 116, 114, 97, 99, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 121, 109, 109, 101, 116, 114, 105, 99, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 110, 118, 101, 114, 115, 101, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 84, 121, 112, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 112, 101, 99, 105, 102, 105, 101, 100, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 112, 108, 97, 121, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 115, 65, 98, 115, 116, 114, 97, 99, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 86, 105, 101, 119, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 112, 101, 99, 105, 102, 105, 101, 100, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 112, 108, 97, 121, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 111, 110, 116, 97, 105, 110, 115, 78, 111, 76, 111, 111, 112, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 118, 101, 110, 116, 78, 111, 116, 105, 102, 105, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 71, 101, 110, 101, 114, 105, 99, 65, 116, 116, 114, 105, 98, 117, 116, 101, 86, 97, 108, 117, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 116, 116, 114, 105, 98, 117, 116, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 86, 97, 108, 117, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 86, 97, 114, 105, 97, 110, 116, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 71, 101, 110, 101, 114, 105, 99, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 112, 101, 99, 105, 102, 105, 101, 100, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 112, 108, 97, 121, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 65, 116, 116, 114, 105, 98, 117, 116, 101, 86, 97, 108, 117, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 116, 116, 114, 105, 98, 117, 116, 101, 86, 97, 108, 117, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 71, 101, 110, 101, 114, 105, 99, 65, 116, 116, 114, 105, 98, 117, 116, 101, 86, 97, 108, 117, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 65, 116, 116, 114, 105, 98, 117, 116, 101, 86, 97, 108, 117, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 65, 100, 100, 78, 111, 100, 101, 115, 73, 116, 101, 109, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 97, 114, 101, 110, 116, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 112, 97, 110, 100, 101, 100, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 102, 101, 114, 101, 110, 99, 101, 84, 121, 112, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 101, 100, 78, 101, 119, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 112, 97, 110, 100, 101, 100, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 119, 115, 101, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 81, 117, 97, 108, 105, 102, 105, 101, 100, 78, 97, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 67, 108, 97, 115, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 67, 108, 97, 115, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 121, 112, 101, 68, 101, 102, 105, 110, 105, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 112, 97, 110, 100, 101, 100, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 65, 100, 100, 78, 111, 100, 101, 115, 82, 101, 115, 117, 108, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 100, 100, 101, 100, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 65, 100, 100, 78, 111, 100, 101, 115, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 78, 111, 100, 101, 115, 84, 111, 65, 100, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 115, 84, 111, 65, 100, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 65, 100, 100, 78, 111, 100, 101, 115, 73, 116, 101, 109, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 78, 111, 100, 101, 115, 84, 111, 65, 100, 100, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 65, 100, 100, 78, 111, 100, 101, 115, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 65, 100, 100, 78, 111, 100, 101, 115, 82, 101, 115, 117, 108, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 65, 100, 100, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 73, 116, 101, 109, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 111, 117, 114, 99, 101, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 102, 101, 114, 101, 110, 99, 101, 84, 121, 112, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 115, 70, 111, 114, 119, 97, 114, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 97, 114, 103, 101, 116, 83, 101, 114, 118, 101, 114, 85, 114, 105, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 97, 114, 103, 101, 116, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 112, 97, 110, 100, 101, 100, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 97, 114, 103, 101, 116, 78, 111, 100, 101, 67, 108, 97, 115, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 67, 108, 97, 115, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 65, 100, 100, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 84, 111, 65, 100, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 84, 111, 65, 100, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 65, 100, 100, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 73, 116, 101, 109, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 84, 111, 65, 100, 100, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 65, 100, 100, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 101, 108, 101, 116, 101, 78, 111, 100, 101, 115, 73, 116, 101, 109, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 108, 101, 116, 101, 84, 97, 114, 103, 101, 116, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 101, 108, 101, 116, 101, 78, 111, 100, 101, 115, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 78, 111, 100, 101, 115, 84, 111, 68, 101, 108, 101, 116, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 115, 84, 111, 68, 101, 108, 101, 116, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 68, 101, 108, 101, 116, 101, 78, 111, 100, 101, 115, 73, 116, 101, 109, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 78, 111, 100, 101, 115, 84, 111, 68, 101, 108, 101, 116, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 101, 108, 101, 116, 101, 78, 111, 100, 101, 115, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 101, 108, 101, 116, 101, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 73, 116, 101, 109, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 111, 117, 114, 99, 101, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 102, 101, 114, 101, 110, 99, 101, 84, 121, 112, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 115, 70, 111, 114, 119, 97, 114, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 97, 114, 103, 101, 116, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 112, 97, 110, 100, 101, 100, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 108, 101, 116, 101, 66, 105, 100, 105, 114, 101, 99, 116, 105, 111, 110, 97, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 101, 108, 101, 116, 101, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 84, 111, 68, 101, 108, 101, 116, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 84, 111, 68, 101, 108, 101, 116, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 68, 101, 108, 101, 116, 101, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 73, 116, 101, 109, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 84, 111, 68, 101, 108, 101, 116, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 101, 108, 101, 116, 101, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 65, 116, 116, 114, 105, 98, 117, 116, 101, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 32, 73, 115, 79, 112, 116, 105, 111, 110, 83, 101, 116, 61, 34, 116, 114, 117, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 110, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 65, 99, 99, 101, 115, 115, 76, 101, 118, 101, 108, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 65, 114, 114, 97, 121, 68, 105, 109, 101, 110, 115, 105, 111, 110, 115, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 119, 115, 101, 78, 97, 109, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 67, 111, 110, 116, 97, 105, 110, 115, 78, 111, 76, 111, 111, 112, 115, 34, 32, 86, 97, 108, 117, 101, 61, 34, 56, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 86, 97, 108, 117, 101, 61, 34, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 112, 108, 97, 121, 78, 97, 109, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 54, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 69, 118, 101, 110, 116, 78, 111, 116, 105, 102, 105, 101, 114, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 50, 56, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 69, 120, 101, 99, 117, 116, 97, 98, 108, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 53, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 72, 105, 115, 116, 111, 114, 105, 122, 105, 110, 103, 34, 32, 86, 97, 108, 117, 101, 61, 34, 53, 49, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 73, 110, 118, 101, 114, 115, 101, 78, 97, 109, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 48, 50, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 73, 115, 65, 98, 115, 116, 114, 97, 99, 116, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 48, 52, 56, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 77, 105, 110, 105, 109, 117, 109, 83, 97, 109, 112, 108, 105, 110, 103, 73, 110, 116, 101, 114, 118, 97, 108, 34, 32, 86, 97, 108, 117, 101, 61, 34, 52, 48, 57, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 67, 108, 97, 115, 115, 34, 32, 86, 97, 108, 117, 101, 61, 34, 56, 49, 57, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 73, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 54, 51, 56, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 83, 121, 109, 109, 101, 116, 114, 105, 99, 34, 32, 86, 97, 108, 117, 101, 61, 34, 51, 50, 55, 54, 56, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 65, 99, 99, 101, 115, 115, 76, 101, 118, 101, 108, 34, 32, 86, 97, 108, 117, 101, 61, 34, 54, 53, 53, 51, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 69, 120, 101, 99, 117, 116, 97, 98, 108, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 51, 49, 48, 55, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 54, 50, 49, 52, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 86, 97, 108, 117, 101, 82, 97, 110, 107, 34, 32, 86, 97, 108, 117, 101, 61, 34, 53, 50, 52, 50, 56, 56, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 48, 52, 56, 53, 55, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 86, 97, 108, 117, 101, 70, 111, 114, 86, 97, 114, 105, 97, 98, 108, 101, 84, 121, 112, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 48, 57, 55, 49, 53, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 84, 121, 112, 101, 68, 101, 102, 105, 110, 105, 116, 105, 111, 110, 34, 32, 86, 97, 108, 117, 101, 61, 34, 52, 49, 57, 52, 51, 48, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 86, 97, 108, 117, 101, 61, 34, 56, 51, 56, 56, 54, 48, 56, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 65, 99, 99, 101, 115, 115, 82, 101, 115, 116, 114, 105, 99, 116, 105, 111, 110, 115, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 54, 55, 55, 55, 50, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 65, 99, 99, 101, 115, 115, 76, 101, 118, 101, 108, 69, 120, 34, 32, 86, 97, 108, 117, 101, 61, 34, 51, 51, 53, 53, 52, 52, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 119, 115, 101, 68, 105, 114, 101, 99, 116, 105, 111, 110, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 70, 111, 114, 119, 97, 114, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 73, 110, 118, 101, 114, 115, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 66, 111, 116, 104, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 73, 110, 118, 97, 108, 105, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 51, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 86, 105, 101, 119, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 86, 105, 101, 119, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 105, 109, 101, 115, 116, 97, 109, 112, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 86, 105, 101, 119, 86, 101, 114, 115, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 119, 115, 101, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 119, 115, 101, 68, 105, 114, 101, 99, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 66, 114, 111, 119, 115, 101, 68, 105, 114, 101, 99, 116, 105, 111, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 102, 101, 114, 101, 110, 99, 101, 84, 121, 112, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 110, 99, 108, 117, 100, 101, 83, 117, 98, 116, 121, 112, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 67, 108, 97, 115, 115, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 117, 108, 116, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 119, 115, 101, 82, 101, 115, 117, 108, 116, 77, 97, 115, 107, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 110, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 102, 101, 114, 101, 110, 99, 101, 84, 121, 112, 101, 73, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 73, 115, 70, 111, 114, 119, 97, 114, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 67, 108, 97, 115, 115, 34, 32, 86, 97, 108, 117, 101, 61, 34, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 119, 115, 101, 78, 97, 109, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 56, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 112, 108, 97, 121, 78, 97, 109, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 84, 121, 112, 101, 68, 101, 102, 105, 110, 105, 116, 105, 111, 110, 34, 32, 86, 97, 108, 117, 101, 61, 34, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 65, 108, 108, 34, 32, 86, 97, 108, 117, 101, 61, 34, 54, 51, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 102, 101, 114, 101, 110, 99, 101, 84, 121, 112, 101, 73, 110, 102, 111, 34, 32, 86, 97, 108, 117, 101, 61, 34, 51, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 84, 97, 114, 103, 101, 116, 73, 110, 102, 111, 34, 32, 86, 97, 108, 117, 101, 61, 34, 54, 48, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 102, 101, 114, 101, 110, 99, 101, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 102, 101, 114, 101, 110, 99, 101, 84, 121, 112, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 115, 70, 111, 114, 119, 97, 114, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 112, 97, 110, 100, 101, 100, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 119, 115, 101, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 81, 117, 97, 108, 105, 102, 105, 101, 100, 78, 97, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 112, 108, 97, 121, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 67, 108, 97, 115, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 67, 108, 97, 115, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 121, 112, 101, 68, 101, 102, 105, 110, 105, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 112, 97, 110, 100, 101, 100, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 67, 111, 110, 116, 105, 110, 117, 97, 116, 105, 111, 110, 80, 111, 105, 110, 116, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 119, 115, 101, 82, 101, 115, 117, 108, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 111, 110, 116, 105, 110, 117, 97, 116, 105, 111, 110, 80, 111, 105, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 102, 101, 114, 101, 110, 99, 101, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 119, 115, 101, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 86, 105, 101, 119, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 86, 105, 101, 119, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 101, 100, 77, 97, 120, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 80, 101, 114, 78, 111, 100, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 78, 111, 100, 101, 115, 84, 111, 66, 114, 111, 119, 115, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 115, 84, 111, 66, 114, 111, 119, 115, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 66, 114, 111, 119, 115, 101, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 78, 111, 100, 101, 115, 84, 111, 66, 114, 111, 119, 115, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 119, 115, 101, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 66, 114, 111, 119, 115, 101, 82, 101, 115, 117, 108, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 119, 115, 101, 78, 101, 120, 116, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 108, 101, 97, 115, 101, 67, 111, 110, 116, 105, 110, 117, 97, 116, 105, 111, 110, 80, 111, 105, 110, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 67, 111, 110, 116, 105, 110, 117, 97, 116, 105, 111, 110, 80, 111, 105, 110, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 111, 110, 116, 105, 110, 117, 97, 116, 105, 111, 110, 80, 111, 105, 110, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 67, 111, 110, 116, 105, 110, 117, 97, 116, 105, 111, 110, 80, 111, 105, 110, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 119, 115, 101, 78, 101, 120, 116, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 66, 114, 111, 119, 115, 101, 82, 101, 115, 117, 108, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 108, 97, 116, 105, 118, 101, 80, 97, 116, 104, 69, 108, 101, 109, 101, 110, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 102, 101, 114, 101, 110, 99, 101, 84, 121, 112, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 115, 73, 110, 118, 101, 114, 115, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 110, 99, 108, 117, 100, 101, 83, 117, 98, 116, 121, 112, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 97, 114, 103, 101, 116, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 81, 117, 97, 108, 105, 102, 105, 101, 100, 78, 97, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 108, 97, 116, 105, 118, 101, 80, 97, 116, 104, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 69, 108, 101, 109, 101, 110, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 108, 101, 109, 101, 110, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 108, 97, 116, 105, 118, 101, 80, 97, 116, 104, 69, 108, 101, 109, 101, 110, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 69, 108, 101, 109, 101, 110, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 119, 115, 101, 80, 97, 116, 104, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 114, 116, 105, 110, 103, 78, 111, 100, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 108, 97, 116, 105, 118, 101, 80, 97, 116, 104, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 108, 97, 116, 105, 118, 101, 80, 97, 116, 104, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 119, 115, 101, 80, 97, 116, 104, 84, 97, 114, 103, 101, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 97, 114, 103, 101, 116, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 112, 97, 110, 100, 101, 100, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 109, 97, 105, 110, 105, 110, 103, 80, 97, 116, 104, 73, 110, 100, 101, 120, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 119, 115, 101, 80, 97, 116, 104, 82, 101, 115, 117, 108, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 84, 97, 114, 103, 101, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 97, 114, 103, 101, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 66, 114, 111, 119, 115, 101, 80, 97, 116, 104, 84, 97, 114, 103, 101, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 84, 97, 114, 103, 101, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 84, 114, 97, 110, 115, 108, 97, 116, 101, 66, 114, 111, 119, 115, 101, 80, 97, 116, 104, 115, 84, 111, 78, 111, 100, 101, 73, 100, 115, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 66, 114, 111, 119, 115, 101, 80, 97, 116, 104, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 119, 115, 101, 80, 97, 116, 104, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 66, 114, 111, 119, 115, 101, 80, 97, 116, 104, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 66, 114, 111, 119, 115, 101, 80, 97, 116, 104, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 84, 114, 97, 110, 115, 108, 97, 116, 101, 66, 114, 111, 119, 115, 101, 80, 97, 116, 104, 115, 84, 111, 78, 111, 100, 101, 73, 100, 115, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 66, 114, 111, 119, 115, 101, 80, 97, 116, 104, 82, 101, 115, 117, 108, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 103, 105, 115, 116, 101, 114, 78, 111, 100, 101, 115, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 78, 111, 100, 101, 115, 84, 111, 82, 101, 103, 105, 115, 116, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 115, 84, 111, 82, 101, 103, 105, 115, 116, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 78, 111, 100, 101, 115, 84, 111, 82, 101, 103, 105, 115, 116, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 103, 105, 115, 116, 101, 114, 78, 111, 100, 101, 115, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 103, 105, 115, 116, 101, 114, 101, 100, 78, 111, 100, 101, 73, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 103, 105, 115, 116, 101, 114, 101, 100, 78, 111, 100, 101, 73, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 103, 105, 115, 116, 101, 114, 101, 100, 78, 111, 100, 101, 73, 100, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 85, 110, 114, 101, 103, 105, 115, 116, 101, 114, 78, 111, 100, 101, 115, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 78, 111, 100, 101, 115, 84, 111, 85, 110, 114, 101, 103, 105, 115, 116, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 115, 84, 111, 85, 110, 114, 101, 103, 105, 115, 116, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 78, 111, 100, 101, 115, 84, 111, 85, 110, 114, 101, 103, 105, 115, 116, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 85, 110, 114, 101, 103, 105, 115, 116, 101, 114, 78, 111, 100, 101, 115, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 67, 111, 117, 110, 116, 101, 114, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 78, 117, 109, 101, 114, 105, 99, 82, 97, 110, 103, 101, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 69, 110, 100, 112, 111, 105, 110, 116, 67, 111, 110, 102, 105, 103, 117, 114, 97, 116, 105, 111, 110, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 79, 112, 101, 114, 97, 116, 105, 111, 110, 84, 105, 109, 101, 111, 117, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 66, 105, 110, 97, 114, 121, 69, 110, 99, 111, 100, 105, 110, 103, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 97, 120, 83, 116, 114, 105, 110, 103, 76, 101, 110, 103, 116, 104, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 97, 120, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 76, 101, 110, 103, 116, 104, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 97, 120, 65, 114, 114, 97, 121, 76, 101, 110, 103, 116, 104, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 97, 120, 77, 101, 115, 115, 97, 103, 101, 83, 105, 122, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 97, 120, 66, 117, 102, 102, 101, 114, 83, 105, 122, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 104, 97, 110, 110, 101, 108, 76, 105, 102, 101, 116, 105, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 99, 117, 114, 105, 116, 121, 84, 111, 107, 101, 110, 76, 105, 102, 101, 116, 105, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 81, 117, 101, 114, 121, 68, 97, 116, 97, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 108, 97, 116, 105, 118, 101, 80, 97, 116, 104, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 108, 97, 116, 105, 118, 101, 80, 97, 116, 104, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 116, 116, 114, 105, 98, 117, 116, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 110, 100, 101, 120, 82, 97, 110, 103, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 84, 121, 112, 101, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 121, 112, 101, 68, 101, 102, 105, 110, 105, 116, 105, 111, 110, 78, 111, 100, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 112, 97, 110, 100, 101, 100, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 110, 99, 108, 117, 100, 101, 83, 117, 98, 84, 121, 112, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 97, 116, 97, 84, 111, 82, 101, 116, 117, 114, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 84, 111, 82, 101, 116, 117, 114, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 81, 117, 101, 114, 121, 68, 97, 116, 97, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 97, 116, 97, 84, 111, 82, 101, 116, 117, 114, 110, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 70, 105, 108, 116, 101, 114, 79, 112, 101, 114, 97, 116, 111, 114, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 69, 113, 117, 97, 108, 115, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 73, 115, 78, 117, 108, 108, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 71, 114, 101, 97, 116, 101, 114, 84, 104, 97, 110, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 76, 101, 115, 115, 84, 104, 97, 110, 34, 32, 86, 97, 108, 117, 101, 61, 34, 51, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 71, 114, 101, 97, 116, 101, 114, 84, 104, 97, 110, 79, 114, 69, 113, 117, 97, 108, 34, 32, 86, 97, 108, 117, 101, 61, 34, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 76, 101, 115, 115, 84, 104, 97, 110, 79, 114, 69, 113, 117, 97, 108, 34, 32, 86, 97, 108, 117, 101, 61, 34, 53, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 76, 105, 107, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 116, 34, 32, 86, 97, 108, 117, 101, 61, 34, 55, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 66, 101, 116, 119, 101, 101, 110, 34, 32, 86, 97, 108, 117, 101, 61, 34, 56, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 73, 110, 76, 105, 115, 116, 34, 32, 86, 97, 108, 117, 101, 61, 34, 57, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 65, 110, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 79, 114, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 67, 97, 115, 116, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 73, 110, 86, 105, 101, 119, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 51, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 79, 102, 84, 121, 112, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 108, 97, 116, 101, 100, 84, 111, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 53, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 66, 105, 116, 119, 105, 115, 101, 65, 110, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 66, 105, 116, 119, 105, 115, 101, 79, 114, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 55, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 81, 117, 101, 114, 121, 68, 97, 116, 97, 83, 101, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 112, 97, 110, 100, 101, 100, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 121, 112, 101, 68, 101, 102, 105, 110, 105, 116, 105, 111, 110, 78, 111, 100, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 112, 97, 110, 100, 101, 100, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 86, 97, 108, 117, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 86, 97, 108, 117, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 86, 97, 114, 105, 97, 110, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 86, 97, 108, 117, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 82, 101, 102, 101, 114, 101, 110, 99, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 102, 101, 114, 101, 110, 99, 101, 84, 121, 112, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 115, 70, 111, 114, 119, 97, 114, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 102, 101, 114, 101, 110, 99, 101, 100, 78, 111, 100, 101, 73, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 102, 101, 114, 101, 110, 99, 101, 100, 78, 111, 100, 101, 73, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 102, 101, 114, 101, 110, 99, 101, 100, 78, 111, 100, 101, 73, 100, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 67, 111, 110, 116, 101, 110, 116, 70, 105, 108, 116, 101, 114, 69, 108, 101, 109, 101, 110, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 70, 105, 108, 116, 101, 114, 79, 112, 101, 114, 97, 116, 111, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 70, 105, 108, 116, 101, 114, 79, 112, 101, 114, 97, 116, 111, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 70, 105, 108, 116, 101, 114, 79, 112, 101, 114, 97, 110, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 70, 105, 108, 116, 101, 114, 79, 112, 101, 114, 97, 110, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 70, 105, 108, 116, 101, 114, 79, 112, 101, 114, 97, 110, 100, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 67, 111, 110, 116, 101, 110, 116, 70, 105, 108, 116, 101, 114, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 69, 108, 101, 109, 101, 110, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 108, 101, 109, 101, 110, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 67, 111, 110, 116, 101, 110, 116, 70, 105, 108, 116, 101, 114, 69, 108, 101, 109, 101, 110, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 69, 108, 101, 109, 101, 110, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 70, 105, 108, 116, 101, 114, 79, 112, 101, 114, 97, 110, 100, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 69, 108, 101, 109, 101, 110, 116, 79, 112, 101, 114, 97, 110, 100, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 70, 105, 108, 116, 101, 114, 79, 112, 101, 114, 97, 110, 100, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 110, 100, 101, 120, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 76, 105, 116, 101, 114, 97, 108, 79, 112, 101, 114, 97, 110, 100, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 70, 105, 108, 116, 101, 114, 79, 112, 101, 114, 97, 110, 100, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 86, 97, 108, 117, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 86, 97, 114, 105, 97, 110, 116, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 65, 116, 116, 114, 105, 98, 117, 116, 101, 79, 112, 101, 114, 97, 110, 100, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 70, 105, 108, 116, 101, 114, 79, 112, 101, 114, 97, 110, 100, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 108, 105, 97, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 119, 115, 101, 80, 97, 116, 104, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 108, 97, 116, 105, 118, 101, 80, 97, 116, 104, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 116, 116, 114, 105, 98, 117, 116, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 110, 100, 101, 120, 82, 97, 110, 103, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 105, 109, 112, 108, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 79, 112, 101, 114, 97, 110, 100, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 70, 105, 108, 116, 101, 114, 79, 112, 101, 114, 97, 110, 100, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 121, 112, 101, 68, 101, 102, 105, 110, 105, 116, 105, 111, 110, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 66, 114, 111, 119, 115, 101, 80, 97, 116, 104, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 119, 115, 101, 80, 97, 116, 104, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 81, 117, 97, 108, 105, 102, 105, 101, 100, 78, 97, 109, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 66, 114, 111, 119, 115, 101, 80, 97, 116, 104, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 116, 116, 114, 105, 98, 117, 116, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 110, 100, 101, 120, 82, 97, 110, 103, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 67, 111, 110, 116, 101, 110, 116, 70, 105, 108, 116, 101, 114, 69, 108, 101, 109, 101, 110, 116, 82, 101, 115, 117, 108, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 79, 112, 101, 114, 97, 110, 100, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 79, 112, 101, 114, 97, 110, 100, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 79, 112, 101, 114, 97, 110, 100, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 79, 112, 101, 114, 97, 110, 100, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 79, 112, 101, 114, 97, 110, 100, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 79, 112, 101, 114, 97, 110, 100, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 67, 111, 110, 116, 101, 110, 116, 70, 105, 108, 116, 101, 114, 82, 101, 115, 117, 108, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 69, 108, 101, 109, 101, 110, 116, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 108, 101, 109, 101, 110, 116, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 67, 111, 110, 116, 101, 110, 116, 70, 105, 108, 116, 101, 114, 69, 108, 101, 109, 101, 110, 116, 82, 101, 115, 117, 108, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 69, 108, 101, 109, 101, 110, 116, 82, 101, 115, 117, 108, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 69, 108, 101, 109, 101, 110, 116, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 108, 101, 109, 101, 110, 116, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 69, 108, 101, 109, 101, 110, 116, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 80, 97, 114, 115, 105, 110, 103, 82, 101, 115, 117, 108, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 97, 116, 97, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 97, 116, 97, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 97, 116, 97, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 97, 116, 97, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 81, 117, 101, 114, 121, 70, 105, 114, 115, 116, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 86, 105, 101, 119, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 86, 105, 101, 119, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 78, 111, 100, 101, 84, 121, 112, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 84, 121, 112, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 84, 121, 112, 101, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 78, 111, 100, 101, 84, 121, 112, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 70, 105, 108, 116, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 67, 111, 110, 116, 101, 110, 116, 70, 105, 108, 116, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 97, 120, 68, 97, 116, 97, 83, 101, 116, 115, 84, 111, 82, 101, 116, 117, 114, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 97, 120, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 84, 111, 82, 101, 116, 117, 114, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 81, 117, 101, 114, 121, 70, 105, 114, 115, 116, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 81, 117, 101, 114, 121, 68, 97, 116, 97, 83, 101, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 81, 117, 101, 114, 121, 68, 97, 116, 97, 83, 101, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 81, 117, 101, 114, 121, 68, 97, 116, 97, 83, 101, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 81, 117, 101, 114, 121, 68, 97, 116, 97, 83, 101, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 111, 110, 116, 105, 110, 117, 97, 116, 105, 111, 110, 80, 111, 105, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 80, 97, 114, 115, 105, 110, 103, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 97, 114, 115, 105, 110, 103, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 80, 97, 114, 115, 105, 110, 103, 82, 101, 115, 117, 108, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 80, 97, 114, 115, 105, 110, 103, 82, 101, 115, 117, 108, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 70, 105, 108, 116, 101, 114, 82, 101, 115, 117, 108, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 67, 111, 110, 116, 101, 110, 116, 70, 105, 108, 116, 101, 114, 82, 101, 115, 117, 108, 116, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 81, 117, 101, 114, 121, 78, 101, 120, 116, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 108, 101, 97, 115, 101, 67, 111, 110, 116, 105, 110, 117, 97, 116, 105, 111, 110, 80, 111, 105, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 111, 110, 116, 105, 110, 117, 97, 116, 105, 111, 110, 80, 111, 105, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 81, 117, 101, 114, 121, 78, 101, 120, 116, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 81, 117, 101, 114, 121, 68, 97, 116, 97, 83, 101, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 81, 117, 101, 114, 121, 68, 97, 116, 97, 83, 101, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 81, 117, 101, 114, 121, 68, 97, 116, 97, 83, 101, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 81, 117, 101, 114, 121, 68, 97, 116, 97, 83, 101, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 118, 105, 115, 101, 100, 67, 111, 110, 116, 105, 110, 117, 97, 116, 105, 111, 110, 80, 111, 105, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 84, 105, 109, 101, 115, 116, 97, 109, 112, 115, 84, 111, 82, 101, 116, 117, 114, 110, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 83, 111, 117, 114, 99, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 66, 111, 116, 104, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 101, 105, 116, 104, 101, 114, 34, 32, 86, 97, 108, 117, 101, 61, 34, 51, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 73, 110, 118, 97, 108, 105, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 52, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 97, 100, 86, 97, 108, 117, 101, 73, 100, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 116, 116, 114, 105, 98, 117, 116, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 110, 100, 101, 120, 82, 97, 110, 103, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 69, 110, 99, 111, 100, 105, 110, 103, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 81, 117, 97, 108, 105, 102, 105, 101, 100, 78, 97, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 97, 100, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 97, 120, 65, 103, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 105, 109, 101, 115, 116, 97, 109, 112, 115, 84, 111, 82, 101, 116, 117, 114, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 84, 105, 109, 101, 115, 116, 97, 109, 112, 115, 84, 111, 82, 101, 116, 117, 114, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 78, 111, 100, 101, 115, 84, 111, 82, 101, 97, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 115, 84, 111, 82, 101, 97, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 97, 100, 86, 97, 108, 117, 101, 73, 100, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 78, 111, 100, 101, 115, 84, 111, 82, 101, 97, 100, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 97, 100, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 97, 116, 97, 86, 97, 108, 117, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 72, 105, 115, 116, 111, 114, 121, 82, 101, 97, 100, 86, 97, 108, 117, 101, 73, 100, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 110, 100, 101, 120, 82, 97, 110, 103, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 69, 110, 99, 111, 100, 105, 110, 103, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 81, 117, 97, 108, 105, 102, 105, 101, 100, 78, 97, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 111, 110, 116, 105, 110, 117, 97, 116, 105, 111, 110, 80, 111, 105, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 72, 105, 115, 116, 111, 114, 121, 82, 101, 97, 100, 82, 101, 115, 117, 108, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 111, 110, 116, 105, 110, 117, 97, 116, 105, 111, 110, 80, 111, 105, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 72, 105, 115, 116, 111, 114, 121, 68, 97, 116, 97, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 72, 105, 115, 116, 111, 114, 121, 82, 101, 97, 100, 68, 101, 116, 97, 105, 108, 115, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 97, 100, 69, 118, 101, 110, 116, 68, 101, 116, 97, 105, 108, 115, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 72, 105, 115, 116, 111, 114, 121, 82, 101, 97, 100, 68, 101, 116, 97, 105, 108, 115, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 117, 109, 86, 97, 108, 117, 101, 115, 80, 101, 114, 78, 111, 100, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 114, 116, 84, 105, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 110, 100, 84, 105, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 70, 105, 108, 116, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 69, 118, 101, 110, 116, 70, 105, 108, 116, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 97, 100, 82, 97, 119, 77, 111, 100, 105, 102, 105, 101, 100, 68, 101, 116, 97, 105, 108, 115, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 72, 105, 115, 116, 111, 114, 121, 82, 101, 97, 100, 68, 101, 116, 97, 105, 108, 115, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 115, 82, 101, 97, 100, 77, 111, 100, 105, 102, 105, 101, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 114, 116, 84, 105, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 110, 100, 84, 105, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 117, 109, 86, 97, 108, 117, 101, 115, 80, 101, 114, 78, 111, 100, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 116, 117, 114, 110, 66, 111, 117, 110, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 97, 100, 80, 114, 111, 99, 101, 115, 115, 101, 100, 68, 101, 116, 97, 105, 108, 115, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 72, 105, 115, 116, 111, 114, 121, 82, 101, 97, 100, 68, 101, 116, 97, 105, 108, 115, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 114, 116, 84, 105, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 110, 100, 84, 105, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 114, 111, 99, 101, 115, 115, 105, 110, 103, 73, 110, 116, 101, 114, 118, 97, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 65, 103, 103, 114, 101, 103, 97, 116, 101, 84, 121, 112, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 103, 103, 114, 101, 103, 97, 116, 101, 84, 121, 112, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 65, 103, 103, 114, 101, 103, 97, 116, 101, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 103, 103, 114, 101, 103, 97, 116, 101, 67, 111, 110, 102, 105, 103, 117, 114, 97, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 65, 103, 103, 114, 101, 103, 97, 116, 101, 67, 111, 110, 102, 105, 103, 117, 114, 97, 116, 105, 111, 110, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 97, 100, 65, 116, 84, 105, 109, 101, 68, 101, 116, 97, 105, 108, 115, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 72, 105, 115, 116, 111, 114, 121, 82, 101, 97, 100, 68, 101, 116, 97, 105, 108, 115, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 113, 84, 105, 109, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 84, 105, 109, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 113, 84, 105, 109, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 83, 105, 109, 112, 108, 101, 66, 111, 117, 110, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 97, 100, 65, 110, 110, 111, 116, 97, 116, 105, 111, 110, 68, 97, 116, 97, 68, 101, 116, 97, 105, 108, 115, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 72, 105, 115, 116, 111, 114, 121, 82, 101, 97, 100, 68, 101, 116, 97, 105, 108, 115, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 113, 84, 105, 109, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 84, 105, 109, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 113, 84, 105, 109, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 72, 105, 115, 116, 111, 114, 121, 68, 97, 116, 97, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 97, 116, 97, 86, 97, 108, 117, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 86, 97, 108, 117, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 97, 116, 97, 86, 97, 108, 117, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 97, 116, 97, 86, 97, 108, 117, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 77, 111, 100, 105, 102, 105, 99, 97, 116, 105, 111, 110, 73, 110, 102, 111, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 111, 100, 105, 102, 105, 99, 97, 116, 105, 111, 110, 84, 105, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 112, 100, 97, 116, 101, 84, 121, 112, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 72, 105, 115, 116, 111, 114, 121, 85, 112, 100, 97, 116, 101, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 72, 105, 115, 116, 111, 114, 121, 77, 111, 100, 105, 102, 105, 101, 100, 68, 97, 116, 97, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 72, 105, 115, 116, 111, 114, 121, 68, 97, 116, 97, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 97, 116, 97, 86, 97, 108, 117, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 86, 97, 108, 117, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 97, 116, 97, 86, 97, 108, 117, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 97, 116, 97, 86, 97, 108, 117, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 77, 111, 100, 105, 102, 105, 99, 97, 116, 105, 111, 110, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 111, 100, 105, 102, 105, 99, 97, 116, 105, 111, 110, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 77, 111, 100, 105, 102, 105, 99, 97, 116, 105, 111, 110, 73, 110, 102, 111, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 77, 111, 100, 105, 102, 105, 99, 97, 116, 105, 111, 110, 73, 110, 102, 111, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 72, 105, 115, 116, 111, 114, 121, 69, 118, 101, 110, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 69, 118, 101, 110, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 118, 101, 110, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 72, 105, 115, 116, 111, 114, 121, 69, 118, 101, 110, 116, 70, 105, 101, 108, 100, 76, 105, 115, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 69, 118, 101, 110, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 72, 105, 115, 116, 111, 114, 121, 82, 101, 97, 100, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 72, 105, 115, 116, 111, 114, 121, 82, 101, 97, 100, 68, 101, 116, 97, 105, 108, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 105, 109, 101, 115, 116, 97, 109, 112, 115, 84, 111, 82, 101, 116, 117, 114, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 84, 105, 109, 101, 115, 116, 97, 109, 112, 115, 84, 111, 82, 101, 116, 117, 114, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 108, 101, 97, 115, 101, 67, 111, 110, 116, 105, 110, 117, 97, 116, 105, 111, 110, 80, 111, 105, 110, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 78, 111, 100, 101, 115, 84, 111, 82, 101, 97, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 115, 84, 111, 82, 101, 97, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 72, 105, 115, 116, 111, 114, 121, 82, 101, 97, 100, 86, 97, 108, 117, 101, 73, 100, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 78, 111, 100, 101, 115, 84, 111, 82, 101, 97, 100, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 72, 105, 115, 116, 111, 114, 121, 82, 101, 97, 100, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 72, 105, 115, 116, 111, 114, 121, 82, 101, 97, 100, 82, 101, 115, 117, 108, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 86, 97, 108, 117, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 116, 116, 114, 105, 98, 117, 116, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 110, 100, 101, 120, 82, 97, 110, 103, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 86, 97, 108, 117, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 97, 116, 97, 86, 97, 108, 117, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 78, 111, 100, 101, 115, 84, 111, 87, 114, 105, 116, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 115, 84, 111, 87, 114, 105, 116, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 87, 114, 105, 116, 101, 86, 97, 108, 117, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 78, 111, 100, 101, 115, 84, 111, 87, 114, 105, 116, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 72, 105, 115, 116, 111, 114, 121, 85, 112, 100, 97, 116, 101, 68, 101, 116, 97, 105, 108, 115, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 72, 105, 115, 116, 111, 114, 121, 85, 112, 100, 97, 116, 101, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 73, 110, 115, 101, 114, 116, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 112, 108, 97, 99, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 85, 112, 100, 97, 116, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 51, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 68, 101, 108, 101, 116, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 52, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 80, 101, 114, 102, 111, 114, 109, 85, 112, 100, 97, 116, 101, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 73, 110, 115, 101, 114, 116, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 112, 108, 97, 99, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 85, 112, 100, 97, 116, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 51, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 109, 111, 118, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 52, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 85, 112, 100, 97, 116, 101, 68, 97, 116, 97, 68, 101, 116, 97, 105, 108, 115, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 72, 105, 115, 116, 111, 114, 121, 85, 112, 100, 97, 116, 101, 68, 101, 116, 97, 105, 108, 115, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 72, 105, 115, 116, 111, 114, 121, 85, 112, 100, 97, 116, 101, 68, 101, 116, 97, 105, 108, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 101, 114, 102, 111, 114, 109, 73, 110, 115, 101, 114, 116, 82, 101, 112, 108, 97, 99, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 80, 101, 114, 102, 111, 114, 109, 85, 112, 100, 97, 116, 101, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 85, 112, 100, 97, 116, 101, 86, 97, 108, 117, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 112, 100, 97, 116, 101, 86, 97, 108, 117, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 97, 116, 97, 86, 97, 108, 117, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 85, 112, 100, 97, 116, 101, 86, 97, 108, 117, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 85, 112, 100, 97, 116, 101, 83, 116, 114, 117, 99, 116, 117, 114, 101, 68, 97, 116, 97, 68, 101, 116, 97, 105, 108, 115, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 72, 105, 115, 116, 111, 114, 121, 85, 112, 100, 97, 116, 101, 68, 101, 116, 97, 105, 108, 115, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 72, 105, 115, 116, 111, 114, 121, 85, 112, 100, 97, 116, 101, 68, 101, 116, 97, 105, 108, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 101, 114, 102, 111, 114, 109, 73, 110, 115, 101, 114, 116, 82, 101, 112, 108, 97, 99, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 80, 101, 114, 102, 111, 114, 109, 85, 112, 100, 97, 116, 101, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 85, 112, 100, 97, 116, 101, 86, 97, 108, 117, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 112, 100, 97, 116, 101, 86, 97, 108, 117, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 97, 116, 97, 86, 97, 108, 117, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 85, 112, 100, 97, 116, 101, 86, 97, 108, 117, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 85, 112, 100, 97, 116, 101, 69, 118, 101, 110, 116, 68, 101, 116, 97, 105, 108, 115, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 72, 105, 115, 116, 111, 114, 121, 85, 112, 100, 97, 116, 101, 68, 101, 116, 97, 105, 108, 115, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 72, 105, 115, 116, 111, 114, 121, 85, 112, 100, 97, 116, 101, 68, 101, 116, 97, 105, 108, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 101, 114, 102, 111, 114, 109, 73, 110, 115, 101, 114, 116, 82, 101, 112, 108, 97, 99, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 80, 101, 114, 102, 111, 114, 109, 85, 112, 100, 97, 116, 101, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 70, 105, 108, 116, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 69, 118, 101, 110, 116, 70, 105, 108, 116, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 69, 118, 101, 110, 116, 68, 97, 116, 97, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 118, 101, 110, 116, 68, 97, 116, 97, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 72, 105, 115, 116, 111, 114, 121, 69, 118, 101, 110, 116, 70, 105, 101, 108, 100, 76, 105, 115, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 69, 118, 101, 110, 116, 68, 97, 116, 97, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 101, 108, 101, 116, 101, 82, 97, 119, 77, 111, 100, 105, 102, 105, 101, 100, 68, 101, 116, 97, 105, 108, 115, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 72, 105, 115, 116, 111, 114, 121, 85, 112, 100, 97, 116, 101, 68, 101, 116, 97, 105, 108, 115, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 72, 105, 115, 116, 111, 114, 121, 85, 112, 100, 97, 116, 101, 68, 101, 116, 97, 105, 108, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 115, 68, 101, 108, 101, 116, 101, 77, 111, 100, 105, 102, 105, 101, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 114, 116, 84, 105, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 110, 100, 84, 105, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 101, 108, 101, 116, 101, 65, 116, 84, 105, 109, 101, 68, 101, 116, 97, 105, 108, 115, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 72, 105, 115, 116, 111, 114, 121, 85, 112, 100, 97, 116, 101, 68, 101, 116, 97, 105, 108, 115, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 72, 105, 115, 116, 111, 114, 121, 85, 112, 100, 97, 116, 101, 68, 101, 116, 97, 105, 108, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 113, 84, 105, 109, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 84, 105, 109, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 113, 84, 105, 109, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 101, 108, 101, 116, 101, 69, 118, 101, 110, 116, 68, 101, 116, 97, 105, 108, 115, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 72, 105, 115, 116, 111, 114, 121, 85, 112, 100, 97, 116, 101, 68, 101, 116, 97, 105, 108, 115, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 72, 105, 115, 116, 111, 114, 121, 85, 112, 100, 97, 116, 101, 68, 101, 116, 97, 105, 108, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 69, 118, 101, 110, 116, 73, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 118, 101, 110, 116, 73, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 69, 118, 101, 110, 116, 73, 100, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 72, 105, 115, 116, 111, 114, 121, 85, 112, 100, 97, 116, 101, 82, 101, 115, 117, 108, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 79, 112, 101, 114, 97, 116, 105, 111, 110, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 79, 112, 101, 114, 97, 116, 105, 111, 110, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 79, 112, 101, 114, 97, 116, 105, 111, 110, 82, 101, 115, 117, 108, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 72, 105, 115, 116, 111, 114, 121, 85, 112, 100, 97, 116, 101, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 72, 105, 115, 116, 111, 114, 121, 85, 112, 100, 97, 116, 101, 68, 101, 116, 97, 105, 108, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 72, 105, 115, 116, 111, 114, 121, 85, 112, 100, 97, 116, 101, 68, 101, 116, 97, 105, 108, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 72, 105, 115, 116, 111, 114, 121, 85, 112, 100, 97, 116, 101, 68, 101, 116, 97, 105, 108, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 72, 105, 115, 116, 111, 114, 121, 85, 112, 100, 97, 116, 101, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 72, 105, 115, 116, 111, 114, 121, 85, 112, 100, 97, 116, 101, 82, 101, 115, 117, 108, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 67, 97, 108, 108, 77, 101, 116, 104, 111, 100, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 79, 98, 106, 101, 99, 116, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 101, 116, 104, 111, 100, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 73, 110, 112, 117, 116, 65, 114, 103, 117, 109, 101, 110, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 110, 112, 117, 116, 65, 114, 103, 117, 109, 101, 110, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 86, 97, 114, 105, 97, 110, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 73, 110, 112, 117, 116, 65, 114, 103, 117, 109, 101, 110, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 67, 97, 108, 108, 77, 101, 116, 104, 111, 100, 82, 101, 115, 117, 108, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 73, 110, 112, 117, 116, 65, 114, 103, 117, 109, 101, 110, 116, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 110, 112, 117, 116, 65, 114, 103, 117, 109, 101, 110, 116, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 73, 110, 112, 117, 116, 65, 114, 103, 117, 109, 101, 110, 116, 82, 101, 115, 117, 108, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 73, 110, 112, 117, 116, 65, 114, 103, 117, 109, 101, 110, 116, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 110, 112, 117, 116, 65, 114, 103, 117, 109, 101, 110, 116, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 73, 110, 112, 117, 116, 65, 114, 103, 117, 109, 101, 110, 116, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 79, 117, 116, 112, 117, 116, 65, 114, 103, 117, 109, 101, 110, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 79, 117, 116, 112, 117, 116, 65, 114, 103, 117, 109, 101, 110, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 86, 97, 114, 105, 97, 110, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 79, 117, 116, 112, 117, 116, 65, 114, 103, 117, 109, 101, 110, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 67, 97, 108, 108, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 77, 101, 116, 104, 111, 100, 115, 84, 111, 67, 97, 108, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 101, 116, 104, 111, 100, 115, 84, 111, 67, 97, 108, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 67, 97, 108, 108, 77, 101, 116, 104, 111, 100, 82, 101, 113, 117, 101, 115, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 77, 101, 116, 104, 111, 100, 115, 84, 111, 67, 97, 108, 108, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 67, 97, 108, 108, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 67, 97, 108, 108, 77, 101, 116, 104, 111, 100, 82, 101, 115, 117, 108, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 77, 111, 110, 105, 116, 111, 114, 105, 110, 103, 77, 111, 100, 101, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 97, 98, 108, 101, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 83, 97, 109, 112, 108, 105, 110, 103, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 112, 111, 114, 116, 105, 110, 103, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 67, 104, 97, 110, 103, 101, 84, 114, 105, 103, 103, 101, 114, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 116, 117, 115, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 116, 117, 115, 86, 97, 108, 117, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 116, 117, 115, 86, 97, 108, 117, 101, 84, 105, 109, 101, 115, 116, 97, 109, 112, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 101, 97, 100, 98, 97, 110, 100, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 110, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 65, 98, 115, 111, 108, 117, 116, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 80, 101, 114, 99, 101, 110, 116, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 77, 111, 110, 105, 116, 111, 114, 105, 110, 103, 70, 105, 108, 116, 101, 114, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 67, 104, 97, 110, 103, 101, 70, 105, 108, 116, 101, 114, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 77, 111, 110, 105, 116, 111, 114, 105, 110, 103, 70, 105, 108, 116, 101, 114, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 114, 105, 103, 103, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 68, 97, 116, 97, 67, 104, 97, 110, 103, 101, 84, 114, 105, 103, 103, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 97, 100, 98, 97, 110, 100, 84, 121, 112, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 97, 100, 98, 97, 110, 100, 86, 97, 108, 117, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 69, 118, 101, 110, 116, 70, 105, 108, 116, 101, 114, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 77, 111, 110, 105, 116, 111, 114, 105, 110, 103, 70, 105, 108, 116, 101, 114, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 83, 101, 108, 101, 99, 116, 67, 108, 97, 117, 115, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 108, 101, 99, 116, 67, 108, 97, 117, 115, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 105, 109, 112, 108, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 79, 112, 101, 114, 97, 110, 100, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 83, 101, 108, 101, 99, 116, 67, 108, 97, 117, 115, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 87, 104, 101, 114, 101, 67, 108, 97, 117, 115, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 67, 111, 110, 116, 101, 110, 116, 70, 105, 108, 116, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 65, 103, 103, 114, 101, 103, 97, 116, 101, 67, 111, 110, 102, 105, 103, 117, 114, 97, 116, 105, 111, 110, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 83, 101, 114, 118, 101, 114, 67, 97, 112, 97, 98, 105, 108, 105, 116, 105, 101, 115, 68, 101, 102, 97, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 114, 101, 97, 116, 85, 110, 99, 101, 114, 116, 97, 105, 110, 65, 115, 66, 97, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 101, 114, 99, 101, 110, 116, 68, 97, 116, 97, 66, 97, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 101, 114, 99, 101, 110, 116, 68, 97, 116, 97, 71, 111, 111, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 83, 108, 111, 112, 101, 100, 69, 120, 116, 114, 97, 112, 111, 108, 97, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 65, 103, 103, 114, 101, 103, 97, 116, 101, 70, 105, 108, 116, 101, 114, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 77, 111, 110, 105, 116, 111, 114, 105, 110, 103, 70, 105, 108, 116, 101, 114, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 114, 116, 84, 105, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 103, 103, 114, 101, 103, 97, 116, 101, 84, 121, 112, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 114, 111, 99, 101, 115, 115, 105, 110, 103, 73, 110, 116, 101, 114, 118, 97, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 103, 103, 114, 101, 103, 97, 116, 101, 67, 111, 110, 102, 105, 103, 117, 114, 97, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 65, 103, 103, 114, 101, 103, 97, 116, 101, 67, 111, 110, 102, 105, 103, 117, 114, 97, 116, 105, 111, 110, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 77, 111, 110, 105, 116, 111, 114, 105, 110, 103, 70, 105, 108, 116, 101, 114, 82, 101, 115, 117, 108, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 69, 118, 101, 110, 116, 70, 105, 108, 116, 101, 114, 82, 101, 115, 117, 108, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 77, 111, 110, 105, 116, 111, 114, 105, 110, 103, 70, 105, 108, 116, 101, 114, 82, 101, 115, 117, 108, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 83, 101, 108, 101, 99, 116, 67, 108, 97, 117, 115, 101, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 108, 101, 99, 116, 67, 108, 97, 117, 115, 101, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 83, 101, 108, 101, 99, 116, 67, 108, 97, 117, 115, 101, 82, 101, 115, 117, 108, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 83, 101, 108, 101, 99, 116, 67, 108, 97, 117, 115, 101, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 108, 101, 99, 116, 67, 108, 97, 117, 115, 101, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 83, 101, 108, 101, 99, 116, 67, 108, 97, 117, 115, 101, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 87, 104, 101, 114, 101, 67, 108, 97, 117, 115, 101, 82, 101, 115, 117, 108, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 67, 111, 110, 116, 101, 110, 116, 70, 105, 108, 116, 101, 114, 82, 101, 115, 117, 108, 116, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 65, 103, 103, 114, 101, 103, 97, 116, 101, 70, 105, 108, 116, 101, 114, 82, 101, 115, 117, 108, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 77, 111, 110, 105, 116, 111, 114, 105, 110, 103, 70, 105, 108, 116, 101, 114, 82, 101, 115, 117, 108, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 118, 105, 115, 101, 100, 83, 116, 97, 114, 116, 84, 105, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 118, 105, 115, 101, 100, 80, 114, 111, 99, 101, 115, 115, 105, 110, 103, 73, 110, 116, 101, 114, 118, 97, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 118, 105, 115, 101, 100, 65, 103, 103, 114, 101, 103, 97, 116, 101, 67, 111, 110, 102, 105, 103, 117, 114, 97, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 65, 103, 103, 114, 101, 103, 97, 116, 101, 67, 111, 110, 102, 105, 103, 117, 114, 97, 116, 105, 111, 110, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 77, 111, 110, 105, 116, 111, 114, 105, 110, 103, 80, 97, 114, 97, 109, 101, 116, 101, 114, 115, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 108, 105, 101, 110, 116, 72, 97, 110, 100, 108, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 97, 109, 112, 108, 105, 110, 103, 73, 110, 116, 101, 114, 118, 97, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 70, 105, 108, 116, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 81, 117, 101, 117, 101, 83, 105, 122, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 99, 97, 114, 100, 79, 108, 100, 101, 115, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 67, 114, 101, 97, 116, 101, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 116, 101, 109, 84, 111, 77, 111, 110, 105, 116, 111, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 97, 100, 86, 97, 108, 117, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 111, 110, 105, 116, 111, 114, 105, 110, 103, 77, 111, 100, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 77, 111, 110, 105, 116, 111, 114, 105, 110, 103, 77, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 101, 100, 80, 97, 114, 97, 109, 101, 116, 101, 114, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 77, 111, 110, 105, 116, 111, 114, 105, 110, 103, 80, 97, 114, 97, 109, 101, 116, 101, 114, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 67, 114, 101, 97, 116, 101, 82, 101, 115, 117, 108, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 118, 105, 115, 101, 100, 83, 97, 109, 112, 108, 105, 110, 103, 73, 110, 116, 101, 114, 118, 97, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 118, 105, 115, 101, 100, 81, 117, 101, 117, 101, 83, 105, 122, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 70, 105, 108, 116, 101, 114, 82, 101, 115, 117, 108, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 67, 114, 101, 97, 116, 101, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 115, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 105, 109, 101, 115, 116, 97, 109, 112, 115, 84, 111, 82, 101, 116, 117, 114, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 84, 105, 109, 101, 115, 116, 97, 109, 112, 115, 84, 111, 82, 101, 116, 117, 114, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 73, 116, 101, 109, 115, 84, 111, 67, 114, 101, 97, 116, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 116, 101, 109, 115, 84, 111, 67, 114, 101, 97, 116, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 67, 114, 101, 97, 116, 101, 82, 101, 113, 117, 101, 115, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 73, 116, 101, 109, 115, 84, 111, 67, 114, 101, 97, 116, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 67, 114, 101, 97, 116, 101, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 115, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 67, 114, 101, 97, 116, 101, 82, 101, 115, 117, 108, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 77, 111, 100, 105, 102, 121, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 101, 100, 80, 97, 114, 97, 109, 101, 116, 101, 114, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 77, 111, 110, 105, 116, 111, 114, 105, 110, 103, 80, 97, 114, 97, 109, 101, 116, 101, 114, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 77, 111, 100, 105, 102, 121, 82, 101, 115, 117, 108, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 118, 105, 115, 101, 100, 83, 97, 109, 112, 108, 105, 110, 103, 73, 110, 116, 101, 114, 118, 97, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 118, 105, 115, 101, 100, 81, 117, 101, 117, 101, 83, 105, 122, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 70, 105, 108, 116, 101, 114, 82, 101, 115, 117, 108, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 77, 111, 100, 105, 102, 121, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 115, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 105, 109, 101, 115, 116, 97, 109, 112, 115, 84, 111, 82, 101, 116, 117, 114, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 84, 105, 109, 101, 115, 116, 97, 109, 112, 115, 84, 111, 82, 101, 116, 117, 114, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 73, 116, 101, 109, 115, 84, 111, 77, 111, 100, 105, 102, 121, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 116, 101, 109, 115, 84, 111, 77, 111, 100, 105, 102, 121, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 77, 111, 100, 105, 102, 121, 82, 101, 113, 117, 101, 115, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 73, 116, 101, 109, 115, 84, 111, 77, 111, 100, 105, 102, 121, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 77, 111, 100, 105, 102, 121, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 115, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 77, 111, 100, 105, 102, 121, 82, 101, 115, 117, 108, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 101, 116, 77, 111, 110, 105, 116, 111, 114, 105, 110, 103, 77, 111, 100, 101, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 111, 110, 105, 116, 111, 114, 105, 110, 103, 77, 111, 100, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 77, 111, 110, 105, 116, 111, 114, 105, 110, 103, 77, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 73, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 73, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 73, 100, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 101, 116, 77, 111, 110, 105, 116, 111, 114, 105, 110, 103, 77, 111, 100, 101, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 101, 116, 84, 114, 105, 103, 103, 101, 114, 105, 110, 103, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 114, 105, 103, 103, 101, 114, 105, 110, 103, 73, 116, 101, 109, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 76, 105, 110, 107, 115, 84, 111, 65, 100, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 76, 105, 110, 107, 115, 84, 111, 65, 100, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 76, 105, 110, 107, 115, 84, 111, 65, 100, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 76, 105, 110, 107, 115, 84, 111, 82, 101, 109, 111, 118, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 76, 105, 110, 107, 115, 84, 111, 82, 101, 109, 111, 118, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 76, 105, 110, 107, 115, 84, 111, 82, 101, 109, 111, 118, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 101, 116, 84, 114, 105, 103, 103, 101, 114, 105, 110, 103, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 65, 100, 100, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 100, 100, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 65, 100, 100, 82, 101, 115, 117, 108, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 65, 100, 100, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 100, 100, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 65, 100, 100, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 109, 111, 118, 101, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 109, 111, 118, 101, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 109, 111, 118, 101, 82, 101, 115, 117, 108, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 109, 111, 118, 101, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 109, 111, 118, 101, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 109, 111, 118, 101, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 101, 108, 101, 116, 101, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 115, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 73, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 73, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 73, 100, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 101, 108, 101, 116, 101, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 115, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 67, 114, 101, 97, 116, 101, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 101, 100, 80, 117, 98, 108, 105, 115, 104, 105, 110, 103, 73, 110, 116, 101, 114, 118, 97, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 101, 100, 76, 105, 102, 101, 116, 105, 109, 101, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 101, 100, 77, 97, 120, 75, 101, 101, 112, 65, 108, 105, 118, 101, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 97, 120, 78, 111, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 115, 80, 101, 114, 80, 117, 98, 108, 105, 115, 104, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 117, 98, 108, 105, 115, 104, 105, 110, 103, 69, 110, 97, 98, 108, 101, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 114, 105, 111, 114, 105, 116, 121, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 67, 114, 101, 97, 116, 101, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 118, 105, 115, 101, 100, 80, 117, 98, 108, 105, 115, 104, 105, 110, 103, 73, 110, 116, 101, 114, 118, 97, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 118, 105, 115, 101, 100, 76, 105, 102, 101, 116, 105, 109, 101, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 118, 105, 115, 101, 100, 77, 97, 120, 75, 101, 101, 112, 65, 108, 105, 118, 101, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 77, 111, 100, 105, 102, 121, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 101, 100, 80, 117, 98, 108, 105, 115, 104, 105, 110, 103, 73, 110, 116, 101, 114, 118, 97, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 101, 100, 76, 105, 102, 101, 116, 105, 109, 101, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 101, 100, 77, 97, 120, 75, 101, 101, 112, 65, 108, 105, 118, 101, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 97, 120, 78, 111, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 115, 80, 101, 114, 80, 117, 98, 108, 105, 115, 104, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 114, 105, 111, 114, 105, 116, 121, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 77, 111, 100, 105, 102, 121, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 118, 105, 115, 101, 100, 80, 117, 98, 108, 105, 115, 104, 105, 110, 103, 73, 110, 116, 101, 114, 118, 97, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 118, 105, 115, 101, 100, 76, 105, 102, 101, 116, 105, 109, 101, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 118, 105, 115, 101, 100, 77, 97, 120, 75, 101, 101, 112, 65, 108, 105, 118, 101, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 101, 116, 80, 117, 98, 108, 105, 115, 104, 105, 110, 103, 77, 111, 100, 101, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 117, 98, 108, 105, 115, 104, 105, 110, 103, 69, 110, 97, 98, 108, 101, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 73, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 73, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 73, 100, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 101, 116, 80, 117, 98, 108, 105, 115, 104, 105, 110, 103, 77, 111, 100, 101, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 77, 101, 115, 115, 97, 103, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 113, 117, 101, 110, 99, 101, 78, 117, 109, 98, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 117, 98, 108, 105, 115, 104, 84, 105, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 78, 111, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 68, 97, 116, 97, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 68, 97, 116, 97, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 78, 111, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 68, 97, 116, 97, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 68, 97, 116, 97, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 67, 104, 97, 110, 103, 101, 78, 111, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 68, 97, 116, 97, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 78, 111, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 78, 111, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 108, 105, 101, 110, 116, 72, 97, 110, 100, 108, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 86, 97, 108, 117, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 97, 116, 97, 86, 97, 108, 117, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 69, 118, 101, 110, 116, 78, 111, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 76, 105, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 68, 97, 116, 97, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 69, 118, 101, 110, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 118, 101, 110, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 69, 118, 101, 110, 116, 70, 105, 101, 108, 100, 76, 105, 115, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 69, 118, 101, 110, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 69, 118, 101, 110, 116, 70, 105, 101, 108, 100, 76, 105, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 108, 105, 101, 110, 116, 72, 97, 110, 100, 108, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 69, 118, 101, 110, 116, 70, 105, 101, 108, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 118, 101, 110, 116, 70, 105, 101, 108, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 86, 97, 114, 105, 97, 110, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 69, 118, 101, 110, 116, 70, 105, 101, 108, 100, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 72, 105, 115, 116, 111, 114, 121, 69, 118, 101, 110, 116, 70, 105, 101, 108, 100, 76, 105, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 69, 118, 101, 110, 116, 70, 105, 101, 108, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 118, 101, 110, 116, 70, 105, 101, 108, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 86, 97, 114, 105, 97, 110, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 69, 118, 101, 110, 116, 70, 105, 101, 108, 100, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 116, 117, 115, 67, 104, 97, 110, 103, 101, 78, 111, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 68, 97, 116, 97, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 116, 117, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 65, 99, 107, 110, 111, 119, 108, 101, 100, 103, 101, 109, 101, 110, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 113, 117, 101, 110, 99, 101, 78, 117, 109, 98, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 80, 117, 98, 108, 105, 115, 104, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 65, 99, 107, 110, 111, 119, 108, 101, 100, 103, 101, 109, 101, 110, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 65, 99, 107, 110, 111, 119, 108, 101, 100, 103, 101, 109, 101, 110, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 65, 99, 107, 110, 111, 119, 108, 101, 100, 103, 101, 109, 101, 110, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 65, 99, 107, 110, 111, 119, 108, 101, 100, 103, 101, 109, 101, 110, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 80, 117, 98, 108, 105, 115, 104, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 65, 118, 97, 105, 108, 97, 98, 108, 101, 83, 101, 113, 117, 101, 110, 99, 101, 78, 117, 109, 98, 101, 114, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 118, 97, 105, 108, 97, 98, 108, 101, 83, 101, 113, 117, 101, 110, 99, 101, 78, 117, 109, 98, 101, 114, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 65, 118, 97, 105, 108, 97, 98, 108, 101, 83, 101, 113, 117, 101, 110, 99, 101, 78, 117, 109, 98, 101, 114, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 111, 114, 101, 78, 111, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 77, 101, 115, 115, 97, 103, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 78, 111, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 77, 101, 115, 115, 97, 103, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 112, 117, 98, 108, 105, 115, 104, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 116, 114, 97, 110, 115, 109, 105, 116, 83, 101, 113, 117, 101, 110, 99, 101, 78, 117, 109, 98, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 112, 117, 98, 108, 105, 115, 104, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 77, 101, 115, 115, 97, 103, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 78, 111, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 77, 101, 115, 115, 97, 103, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 84, 114, 97, 110, 115, 102, 101, 114, 82, 101, 115, 117, 108, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 65, 118, 97, 105, 108, 97, 98, 108, 101, 83, 101, 113, 117, 101, 110, 99, 101, 78, 117, 109, 98, 101, 114, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 118, 97, 105, 108, 97, 98, 108, 101, 83, 101, 113, 117, 101, 110, 99, 101, 78, 117, 109, 98, 101, 114, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 65, 118, 97, 105, 108, 97, 98, 108, 101, 83, 101, 113, 117, 101, 110, 99, 101, 78, 117, 109, 98, 101, 114, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 84, 114, 97, 110, 115, 102, 101, 114, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 115, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 73, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 73, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 73, 100, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 110, 100, 73, 110, 105, 116, 105, 97, 108, 86, 97, 108, 117, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 84, 114, 97, 110, 115, 102, 101, 114, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 115, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 84, 114, 97, 110, 115, 102, 101, 114, 82, 101, 115, 117, 108, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 101, 108, 101, 116, 101, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 115, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 73, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 73, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 73, 100, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 101, 108, 101, 116, 101, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 115, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 66, 117, 105, 108, 100, 73, 110, 102, 111, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 114, 111, 100, 117, 99, 116, 85, 114, 105, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 97, 110, 117, 102, 97, 99, 116, 117, 114, 101, 114, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 114, 111, 100, 117, 99, 116, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 111, 102, 116, 119, 97, 114, 101, 86, 101, 114, 115, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 117, 105, 108, 100, 78, 117, 109, 98, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 117, 105, 108, 100, 68, 97, 116, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 100, 117, 110, 100, 97, 110, 99, 121, 83, 117, 112, 112, 111, 114, 116, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 110, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 67, 111, 108, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 87, 97, 114, 109, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 72, 111, 116, 34, 32, 86, 97, 108, 117, 101, 61, 34, 51, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 84, 114, 97, 110, 115, 112, 97, 114, 101, 110, 116, 34, 32, 86, 97, 108, 117, 101, 61, 34, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 72, 111, 116, 65, 110, 100, 77, 105, 114, 114, 111, 114, 101, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 53, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 83, 116, 97, 116, 101, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 82, 117, 110, 110, 105, 110, 103, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 70, 97, 105, 108, 101, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 67, 111, 110, 102, 105, 103, 117, 114, 97, 116, 105, 111, 110, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 83, 117, 115, 112, 101, 110, 100, 101, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 51, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 83, 104, 117, 116, 100, 111, 119, 110, 34, 32, 86, 97, 108, 117, 101, 61, 34, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 84, 101, 115, 116, 34, 32, 86, 97, 108, 117, 101, 61, 34, 53, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 67, 111, 109, 109, 117, 110, 105, 99, 97, 116, 105, 111, 110, 70, 97, 117, 108, 116, 34, 32, 86, 97, 108, 117, 101, 61, 34, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 85, 110, 107, 110, 111, 119, 110, 34, 32, 86, 97, 108, 117, 101, 61, 34, 55, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 100, 117, 110, 100, 97, 110, 116, 83, 101, 114, 118, 101, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 105, 99, 101, 76, 101, 118, 101, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 83, 116, 97, 116, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 101, 114, 118, 101, 114, 83, 116, 97, 116, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 69, 110, 100, 112, 111, 105, 110, 116, 85, 114, 108, 76, 105, 115, 116, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 69, 110, 100, 112, 111, 105, 110, 116, 85, 114, 108, 76, 105, 115, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 110, 100, 112, 111, 105, 110, 116, 85, 114, 108, 76, 105, 115, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 69, 110, 100, 112, 111, 105, 110, 116, 85, 114, 108, 76, 105, 115, 116, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 78, 101, 116, 119, 111, 114, 107, 71, 114, 111, 117, 112, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 85, 114, 105, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 78, 101, 116, 119, 111, 114, 107, 80, 97, 116, 104, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 101, 116, 119, 111, 114, 107, 80, 97, 116, 104, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 69, 110, 100, 112, 111, 105, 110, 116, 85, 114, 108, 76, 105, 115, 116, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 78, 101, 116, 119, 111, 114, 107, 80, 97, 116, 104, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 97, 109, 112, 108, 105, 110, 103, 73, 110, 116, 101, 114, 118, 97, 108, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 115, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 97, 109, 112, 108, 105, 110, 103, 73, 110, 116, 101, 114, 118, 97, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 97, 120, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 97, 98, 108, 101, 100, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 115, 83, 117, 109, 109, 97, 114, 121, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 86, 105, 101, 119, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 117, 114, 114, 101, 110, 116, 83, 101, 115, 115, 105, 111, 110, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 117, 109, 117, 108, 97, 116, 101, 100, 83, 101, 115, 115, 105, 111, 110, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 99, 117, 114, 105, 116, 121, 82, 101, 106, 101, 99, 116, 101, 100, 83, 101, 115, 115, 105, 111, 110, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 106, 101, 99, 116, 101, 100, 83, 101, 115, 115, 105, 111, 110, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 115, 115, 105, 111, 110, 84, 105, 109, 101, 111, 117, 116, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 115, 115, 105, 111, 110, 65, 98, 111, 114, 116, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 117, 114, 114, 101, 110, 116, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 117, 109, 117, 108, 97, 116, 101, 100, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 117, 98, 108, 105, 115, 104, 105, 110, 103, 73, 110, 116, 101, 114, 118, 97, 108, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 99, 117, 114, 105, 116, 121, 82, 101, 106, 101, 99, 116, 101, 100, 82, 101, 113, 117, 101, 115, 116, 115, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 106, 101, 99, 116, 101, 100, 82, 101, 113, 117, 101, 115, 116, 115, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 83, 116, 97, 116, 117, 115, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 114, 116, 84, 105, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 117, 114, 114, 101, 110, 116, 84, 105, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 116, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 101, 114, 118, 101, 114, 83, 116, 97, 116, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 117, 105, 108, 100, 73, 110, 102, 111, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 66, 117, 105, 108, 100, 73, 110, 102, 111, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 99, 111, 110, 100, 115, 84, 105, 108, 108, 83, 104, 117, 116, 100, 111, 119, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 104, 117, 116, 100, 111, 119, 110, 82, 101, 97, 115, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 101, 115, 115, 105, 111, 110, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 115, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 115, 115, 105, 111, 110, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 115, 115, 105, 111, 110, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 108, 105, 101, 110, 116, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 65, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 85, 114, 105, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 110, 100, 112, 111, 105, 110, 116, 85, 114, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 76, 111, 99, 97, 108, 101, 73, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 76, 111, 99, 97, 108, 101, 73, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 76, 111, 99, 97, 108, 101, 73, 100, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 99, 116, 117, 97, 108, 83, 101, 115, 115, 105, 111, 110, 84, 105, 109, 101, 111, 117, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 97, 120, 82, 101, 115, 112, 111, 110, 115, 101, 77, 101, 115, 115, 97, 103, 101, 83, 105, 122, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 108, 105, 101, 110, 116, 67, 111, 110, 110, 101, 99, 116, 105, 111, 110, 84, 105, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 108, 105, 101, 110, 116, 76, 97, 115, 116, 67, 111, 110, 116, 97, 99, 116, 84, 105, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 117, 114, 114, 101, 110, 116, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 115, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 117, 114, 114, 101, 110, 116, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 115, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 117, 114, 114, 101, 110, 116, 80, 117, 98, 108, 105, 115, 104, 82, 101, 113, 117, 101, 115, 116, 115, 73, 110, 81, 117, 101, 117, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 111, 116, 97, 108, 82, 101, 113, 117, 101, 115, 116, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 101, 114, 118, 105, 99, 101, 67, 111, 117, 110, 116, 101, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 110, 97, 117, 116, 104, 111, 114, 105, 122, 101, 100, 82, 101, 113, 117, 101, 115, 116, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 97, 100, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 101, 114, 118, 105, 99, 101, 67, 111, 117, 110, 116, 101, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 72, 105, 115, 116, 111, 114, 121, 82, 101, 97, 100, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 101, 114, 118, 105, 99, 101, 67, 111, 117, 110, 116, 101, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 101, 114, 118, 105, 99, 101, 67, 111, 117, 110, 116, 101, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 72, 105, 115, 116, 111, 114, 121, 85, 112, 100, 97, 116, 101, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 101, 114, 118, 105, 99, 101, 67, 111, 117, 110, 116, 101, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 97, 108, 108, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 101, 114, 118, 105, 99, 101, 67, 111, 117, 110, 116, 101, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 114, 101, 97, 116, 101, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 115, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 101, 114, 118, 105, 99, 101, 67, 111, 117, 110, 116, 101, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 111, 100, 105, 102, 121, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 115, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 101, 114, 118, 105, 99, 101, 67, 111, 117, 110, 116, 101, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 116, 77, 111, 110, 105, 116, 111, 114, 105, 110, 103, 77, 111, 100, 101, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 101, 114, 118, 105, 99, 101, 67, 111, 117, 110, 116, 101, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 116, 84, 114, 105, 103, 103, 101, 114, 105, 110, 103, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 101, 114, 118, 105, 99, 101, 67, 111, 117, 110, 116, 101, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 108, 101, 116, 101, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 115, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 101, 114, 118, 105, 99, 101, 67, 111, 117, 110, 116, 101, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 114, 101, 97, 116, 101, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 101, 114, 118, 105, 99, 101, 67, 111, 117, 110, 116, 101, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 111, 100, 105, 102, 121, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 101, 114, 118, 105, 99, 101, 67, 111, 117, 110, 116, 101, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 116, 80, 117, 98, 108, 105, 115, 104, 105, 110, 103, 77, 111, 100, 101, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 101, 114, 118, 105, 99, 101, 67, 111, 117, 110, 116, 101, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 117, 98, 108, 105, 115, 104, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 101, 114, 118, 105, 99, 101, 67, 111, 117, 110, 116, 101, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 112, 117, 98, 108, 105, 115, 104, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 101, 114, 118, 105, 99, 101, 67, 111, 117, 110, 116, 101, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 114, 97, 110, 115, 102, 101, 114, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 115, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 101, 114, 118, 105, 99, 101, 67, 111, 117, 110, 116, 101, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 108, 101, 116, 101, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 115, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 101, 114, 118, 105, 99, 101, 67, 111, 117, 110, 116, 101, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 100, 100, 78, 111, 100, 101, 115, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 101, 114, 118, 105, 99, 101, 67, 111, 117, 110, 116, 101, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 100, 100, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 101, 114, 118, 105, 99, 101, 67, 111, 117, 110, 116, 101, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 108, 101, 116, 101, 78, 111, 100, 101, 115, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 101, 114, 118, 105, 99, 101, 67, 111, 117, 110, 116, 101, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 108, 101, 116, 101, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 101, 114, 118, 105, 99, 101, 67, 111, 117, 110, 116, 101, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 119, 115, 101, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 101, 114, 118, 105, 99, 101, 67, 111, 117, 110, 116, 101, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 119, 115, 101, 78, 101, 120, 116, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 101, 114, 118, 105, 99, 101, 67, 111, 117, 110, 116, 101, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 114, 97, 110, 115, 108, 97, 116, 101, 66, 114, 111, 119, 115, 101, 80, 97, 116, 104, 115, 84, 111, 78, 111, 100, 101, 73, 100, 115, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 101, 114, 118, 105, 99, 101, 67, 111, 117, 110, 116, 101, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 81, 117, 101, 114, 121, 70, 105, 114, 115, 116, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 101, 114, 118, 105, 99, 101, 67, 111, 117, 110, 116, 101, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 81, 117, 101, 114, 121, 78, 101, 120, 116, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 101, 114, 118, 105, 99, 101, 67, 111, 117, 110, 116, 101, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 103, 105, 115, 116, 101, 114, 78, 111, 100, 101, 115, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 101, 114, 118, 105, 99, 101, 67, 111, 117, 110, 116, 101, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 110, 114, 101, 103, 105, 115, 116, 101, 114, 78, 111, 100, 101, 115, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 101, 114, 118, 105, 99, 101, 67, 111, 117, 110, 116, 101, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 101, 115, 115, 105, 111, 110, 83, 101, 99, 117, 114, 105, 116, 121, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 115, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 115, 115, 105, 111, 110, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 108, 105, 101, 110, 116, 85, 115, 101, 114, 73, 100, 79, 102, 83, 101, 115, 115, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 67, 108, 105, 101, 110, 116, 85, 115, 101, 114, 73, 100, 72, 105, 115, 116, 111, 114, 121, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 108, 105, 101, 110, 116, 85, 115, 101, 114, 73, 100, 72, 105, 115, 116, 111, 114, 121, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 67, 108, 105, 101, 110, 116, 85, 115, 101, 114, 73, 100, 72, 105, 115, 116, 111, 114, 121, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 117, 116, 104, 101, 110, 116, 105, 99, 97, 116, 105, 111, 110, 77, 101, 99, 104, 97, 110, 105, 115, 109, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 110, 99, 111, 100, 105, 110, 103, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 114, 97, 110, 115, 112, 111, 114, 116, 80, 114, 111, 116, 111, 99, 111, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 99, 117, 114, 105, 116, 121, 77, 111, 100, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 77, 101, 115, 115, 97, 103, 101, 83, 101, 99, 117, 114, 105, 116, 121, 77, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 99, 117, 114, 105, 116, 121, 80, 111, 108, 105, 99, 121, 85, 114, 105, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 108, 105, 101, 110, 116, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 105, 99, 101, 67, 111, 117, 110, 116, 101, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 111, 116, 97, 108, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 114, 114, 111, 114, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 116, 117, 115, 82, 101, 115, 117, 108, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 115, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 115, 115, 105, 111, 110, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 114, 105, 111, 114, 105, 116, 121, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 117, 98, 108, 105, 115, 104, 105, 110, 103, 73, 110, 116, 101, 114, 118, 97, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 97, 120, 75, 101, 101, 112, 65, 108, 105, 118, 101, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 97, 120, 76, 105, 102, 101, 116, 105, 109, 101, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 97, 120, 78, 111, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 115, 80, 101, 114, 80, 117, 98, 108, 105, 115, 104, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 117, 98, 108, 105, 115, 104, 105, 110, 103, 69, 110, 97, 98, 108, 101, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 111, 100, 105, 102, 121, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 110, 97, 98, 108, 101, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 97, 98, 108, 101, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 112, 117, 98, 108, 105, 115, 104, 82, 101, 113, 117, 101, 115, 116, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 112, 117, 98, 108, 105, 115, 104, 77, 101, 115, 115, 97, 103, 101, 82, 101, 113, 117, 101, 115, 116, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 112, 117, 98, 108, 105, 115, 104, 77, 101, 115, 115, 97, 103, 101, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 114, 97, 110, 115, 102, 101, 114, 82, 101, 113, 117, 101, 115, 116, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 114, 97, 110, 115, 102, 101, 114, 114, 101, 100, 84, 111, 65, 108, 116, 67, 108, 105, 101, 110, 116, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 114, 97, 110, 115, 102, 101, 114, 114, 101, 100, 84, 111, 83, 97, 109, 101, 67, 108, 105, 101, 110, 116, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 117, 98, 108, 105, 115, 104, 82, 101, 113, 117, 101, 115, 116, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 67, 104, 97, 110, 103, 101, 78, 111, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 115, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 118, 101, 110, 116, 78, 111, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 115, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 115, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 76, 97, 116, 101, 80, 117, 98, 108, 105, 115, 104, 82, 101, 113, 117, 101, 115, 116, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 117, 114, 114, 101, 110, 116, 75, 101, 101, 112, 65, 108, 105, 118, 101, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 117, 114, 114, 101, 110, 116, 76, 105, 102, 101, 116, 105, 109, 101, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 110, 97, 99, 107, 110, 111, 119, 108, 101, 100, 103, 101, 100, 77, 101, 115, 115, 97, 103, 101, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 99, 97, 114, 100, 101, 100, 77, 101, 115, 115, 97, 103, 101, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 97, 98, 108, 101, 100, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 111, 110, 105, 116, 111, 114, 105, 110, 103, 81, 117, 101, 117, 101, 79, 118, 101, 114, 102, 108, 111, 119, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 101, 120, 116, 83, 101, 113, 117, 101, 110, 99, 101, 78, 117, 109, 98, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 118, 101, 110, 116, 81, 117, 101, 117, 101, 79, 118, 101, 114, 70, 108, 111, 119, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 77, 111, 100, 101, 108, 67, 104, 97, 110, 103, 101, 83, 116, 114, 117, 99, 116, 117, 114, 101, 86, 101, 114, 98, 77, 97, 115, 107, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 65, 100, 100, 101, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 68, 101, 108, 101, 116, 101, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 102, 101, 114, 101, 110, 99, 101, 65, 100, 100, 101, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 102, 101, 114, 101, 110, 99, 101, 68, 101, 108, 101, 116, 101, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 56, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 84, 121, 112, 101, 67, 104, 97, 110, 103, 101, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 77, 111, 100, 101, 108, 67, 104, 97, 110, 103, 101, 83, 116, 114, 117, 99, 116, 117, 114, 101, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 102, 102, 101, 99, 116, 101, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 102, 102, 101, 99, 116, 101, 100, 84, 121, 112, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 86, 101, 114, 98, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 101, 109, 97, 110, 116, 105, 99, 67, 104, 97, 110, 103, 101, 83, 116, 114, 117, 99, 116, 117, 114, 101, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 102, 102, 101, 99, 116, 101, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 102, 102, 101, 99, 116, 101, 100, 84, 121, 112, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 82, 97, 110, 103, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 76, 111, 119, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 72, 105, 103, 104, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 69, 85, 73, 110, 102, 111, 114, 109, 97, 116, 105, 111, 110, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 101, 115, 112, 97, 99, 101, 85, 114, 105, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 110, 105, 116, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 112, 108, 97, 121, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 65, 120, 105, 115, 83, 99, 97, 108, 101, 69, 110, 117, 109, 101, 114, 97, 116, 105, 111, 110, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 76, 105, 110, 101, 97, 114, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 76, 111, 103, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 76, 110, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 67, 111, 109, 112, 108, 101, 120, 78, 117, 109, 98, 101, 114, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 97, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 70, 108, 111, 97, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 109, 97, 103, 105, 110, 97, 114, 121, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 70, 108, 111, 97, 116, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 111, 117, 98, 108, 101, 67, 111, 109, 112, 108, 101, 120, 78, 117, 109, 98, 101, 114, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 97, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 109, 97, 103, 105, 110, 97, 114, 121, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 65, 120, 105, 115, 73, 110, 102, 111, 114, 109, 97, 116, 105, 111, 110, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 110, 103, 105, 110, 101, 101, 114, 105, 110, 103, 85, 110, 105, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 69, 85, 73, 110, 102, 111, 114, 109, 97, 116, 105, 111, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 85, 82, 97, 110, 103, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 97, 110, 103, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 105, 116, 108, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 120, 105, 115, 83, 99, 97, 108, 101, 84, 121, 112, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 65, 120, 105, 115, 83, 99, 97, 108, 101, 69, 110, 117, 109, 101, 114, 97, 116, 105, 111, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 65, 120, 105, 115, 83, 116, 101, 112, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 120, 105, 115, 83, 116, 101, 112, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 65, 120, 105, 115, 83, 116, 101, 112, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 88, 86, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 88, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 86, 97, 108, 117, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 70, 108, 111, 97, 116, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 80, 114, 111, 103, 114, 97, 109, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 114, 101, 97, 116, 101, 83, 101, 115, 115, 105, 111, 110, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 114, 101, 97, 116, 101, 67, 108, 105, 101, 110, 116, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 110, 118, 111, 99, 97, 116, 105, 111, 110, 67, 114, 101, 97, 116, 105, 111, 110, 84, 105, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 76, 97, 115, 116, 84, 114, 97, 110, 115, 105, 116, 105, 111, 110, 84, 105, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 76, 97, 115, 116, 77, 101, 116, 104, 111, 100, 67, 97, 108, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 76, 97, 115, 116, 77, 101, 116, 104, 111, 100, 83, 101, 115, 115, 105, 111, 110, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 76, 97, 115, 116, 77, 101, 116, 104, 111, 100, 73, 110, 112, 117, 116, 65, 114, 103, 117, 109, 101, 110, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 76, 97, 115, 116, 77, 101, 116, 104, 111, 100, 73, 110, 112, 117, 116, 65, 114, 103, 117, 109, 101, 110, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 65, 114, 103, 117, 109, 101, 110, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 76, 97, 115, 116, 77, 101, 116, 104, 111, 100, 73, 110, 112, 117, 116, 65, 114, 103, 117, 109, 101, 110, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 76, 97, 115, 116, 77, 101, 116, 104, 111, 100, 79, 117, 116, 112, 117, 116, 65, 114, 103, 117, 109, 101, 110, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 76, 97, 115, 116, 77, 101, 116, 104, 111, 100, 79, 117, 116, 112, 117, 116, 65, 114, 103, 117, 109, 101, 110, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 65, 114, 103, 117, 109, 101, 110, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 76, 97, 115, 116, 77, 101, 116, 104, 111, 100, 79, 117, 116, 112, 117, 116, 65, 114, 103, 117, 109, 101, 110, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 76, 97, 115, 116, 77, 101, 116, 104, 111, 100, 67, 97, 108, 108, 84, 105, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 76, 97, 115, 116, 77, 101, 116, 104, 111, 100, 82, 101, 116, 117, 114, 110, 83, 116, 97, 116, 117, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 116, 97, 116, 117, 115, 82, 101, 115, 117, 108, 116, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 80, 114, 111, 103, 114, 97, 109, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 50, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 114, 101, 97, 116, 101, 83, 101, 115, 115, 105, 111, 110, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 114, 101, 97, 116, 101, 67, 108, 105, 101, 110, 116, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 110, 118, 111, 99, 97, 116, 105, 111, 110, 67, 114, 101, 97, 116, 105, 111, 110, 84, 105, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 76, 97, 115, 116, 84, 114, 97, 110, 115, 105, 116, 105, 111, 110, 84, 105, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 76, 97, 115, 116, 77, 101, 116, 104, 111, 100, 67, 97, 108, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 76, 97, 115, 116, 77, 101, 116, 104, 111, 100, 83, 101, 115, 115, 105, 111, 110, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 76, 97, 115, 116, 77, 101, 116, 104, 111, 100, 73, 110, 112, 117, 116, 65, 114, 103, 117, 109, 101, 110, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 76, 97, 115, 116, 77, 101, 116, 104, 111, 100, 73, 110, 112, 117, 116, 65, 114, 103, 117, 109, 101, 110, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 65, 114, 103, 117, 109, 101, 110, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 76, 97, 115, 116, 77, 101, 116, 104, 111, 100, 73, 110, 112, 117, 116, 65, 114, 103, 117, 109, 101, 110, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 76, 97, 115, 116, 77, 101, 116, 104, 111, 100, 79, 117, 116, 112, 117, 116, 65, 114, 103, 117, 109, 101, 110, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 76, 97, 115, 116, 77, 101, 116, 104, 111, 100, 79, 117, 116, 112, 117, 116, 65, 114, 103, 117, 109, 101, 110, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 65, 114, 103, 117, 109, 101, 110, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 76, 97, 115, 116, 77, 101, 116, 104, 111, 100, 79, 117, 116, 112, 117, 116, 65, 114, 103, 117, 109, 101, 110, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 76, 97, 115, 116, 77, 101, 116, 104, 111, 100, 73, 110, 112, 117, 116, 86, 97, 108, 117, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 76, 97, 115, 116, 77, 101, 116, 104, 111, 100, 73, 110, 112, 117, 116, 86, 97, 108, 117, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 86, 97, 114, 105, 97, 110, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 76, 97, 115, 116, 77, 101, 116, 104, 111, 100, 73, 110, 112, 117, 116, 86, 97, 108, 117, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 76, 97, 115, 116, 77, 101, 116, 104, 111, 100, 79, 117, 116, 112, 117, 116, 86, 97, 108, 117, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 76, 97, 115, 116, 77, 101, 116, 104, 111, 100, 79, 117, 116, 112, 117, 116, 86, 97, 108, 117, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 86, 97, 114, 105, 97, 110, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 76, 97, 115, 116, 77, 101, 116, 104, 111, 100, 79, 117, 116, 112, 117, 116, 86, 97, 108, 117, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 76, 97, 115, 116, 77, 101, 116, 104, 111, 100, 67, 97, 108, 108, 84, 105, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 76, 97, 115, 116, 77, 101, 116, 104, 111, 100, 82, 101, 116, 117, 114, 110, 83, 116, 97, 116, 117, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 116, 97, 116, 117, 115, 82, 101, 115, 117, 108, 116, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 65, 110, 110, 111, 116, 97, 116, 105, 111, 110, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 101, 115, 115, 97, 103, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 110, 110, 111, 116, 97, 116, 105, 111, 110, 84, 105, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 69, 120, 99, 101, 112, 116, 105, 111, 110, 68, 101, 118, 105, 97, 116, 105, 111, 110, 70, 111, 114, 109, 97, 116, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 65, 98, 115, 111, 108, 117, 116, 101, 86, 97, 108, 117, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 80, 101, 114, 99, 101, 110, 116, 79, 102, 86, 97, 108, 117, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 80, 101, 114, 99, 101, 110, 116, 79, 102, 82, 97, 110, 103, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 80, 101, 114, 99, 101, 110, 116, 79, 102, 69, 85, 82, 97, 110, 103, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 51, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 85, 110, 107, 110, 111, 119, 110, 34, 32, 86, 97, 108, 117, 101, 61, 34, 52, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 60, 47, 111, 112, 99, 58, 84, 121, 112, 101, 68, 105, 99, 116, 105, 111, 110, 97, 114, 121, 62};
+
+
-static UA_StatusCode function_namespace0_generated_207_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_185_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_VariableAttributes attr = UA_VariableAttributes_default;
attr.minimumSamplingInterval = 0.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 15);
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 15LU);
UA_ByteString *variablenode_ns_0_i_7617_variant_DataContents = UA_ByteString_new();
if (!variablenode_ns_0_i_7617_variant_DataContents) return UA_STATUSCODE_BADOUTOFMEMORY;
UA_ByteString_init(variablenode_ns_0_i_7617_variant_DataContents);
-*variablenode_ns_0_i_7617_variant_DataContents = UA_BYTESTRING_NULL;
+variablenode_ns_0_i_7617_variant_DataContents->length = 177218;
+variablenode_ns_0_i_7617_variant_DataContents->data = (UA_Byte *)(void*)(uintptr_t)variablenode_ns_0_i_7617_variant_DataContents_byteArray;
UA_Variant_setScalar(&attr.value, variablenode_ns_0_i_7617_variant_DataContents, &UA_TYPES[UA_TYPES_BYTESTRING]);
attr.displayName = UA_LOCALIZEDTEXT("", "Opc.Ua");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 7617),
-UA_NODEID_NUMERIC(ns[0], 93),
-UA_NODEID_NUMERIC(ns[0], 47),
+UA_NODEID_NUMERIC(ns[0], 7617LU),
+UA_NODEID_NUMERIC(ns[0], 93LU),
+UA_NODEID_NUMERIC(ns[0], 47LU),
UA_QUALIFIEDNAME(ns[0], "Opc.Ua"),
-UA_NODEID_NUMERIC(ns[0], 72),
+UA_NODEID_NUMERIC(ns[0], 72LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
variablenode_ns_0_i_7617_variant_DataContents->data = NULL;
variablenode_ns_0_i_7617_variant_DataContents->length = 0;
@@ -51762,267 +56874,267 @@ UA_ByteString_delete(variablenode_ns_0_i_7617_variant_DataContents);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_207_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_185_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 7617)
+UA_NODEID_NUMERIC(ns[0], 7617LU)
);
}
/* NamespaceUri - ns=0;i=107 */
-static UA_StatusCode function_namespace0_generated_208_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_186_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_VariableAttributes attr = UA_VariableAttributes_default;
attr.minimumSamplingInterval = 0.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 12);
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 12LU);
attr.displayName = UA_LOCALIZEDTEXT("", "NamespaceUri");
#ifdef UA_ENABLE_NODESET_COMPILER_DESCRIPTIONS
attr.description = UA_LOCALIZEDTEXT("", "A URI that uniquely identifies the dictionary.");
#endif
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 107),
-UA_NODEID_NUMERIC(ns[0], 72),
-UA_NODEID_NUMERIC(ns[0], 46),
+UA_NODEID_NUMERIC(ns[0], 107LU),
+UA_NODEID_NUMERIC(ns[0], 72LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
UA_QUALIFIEDNAME(ns[0], "NamespaceUri"),
-UA_NODEID_NUMERIC(ns[0], 68),
+UA_NODEID_NUMERIC(ns[0], 68LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
-retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 107), UA_NODEID_NUMERIC(ns[0], 37), UA_EXPANDEDNODEID_NUMERIC(ns[0], 80), true);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 107LU), UA_NODEID_NUMERIC(ns[0], 37LU), UA_EXPANDEDNODEID_NUMERIC(ns[0], 80LU), true);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_208_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_186_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 107)
+UA_NODEID_NUMERIC(ns[0], 107LU)
);
}
/* DataTypeVersion - ns=0;i=106 */
-static UA_StatusCode function_namespace0_generated_209_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_187_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_VariableAttributes attr = UA_VariableAttributes_default;
attr.minimumSamplingInterval = 0.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 12);
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 12LU);
attr.displayName = UA_LOCALIZEDTEXT("", "DataTypeVersion");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 106),
-UA_NODEID_NUMERIC(ns[0], 72),
-UA_NODEID_NUMERIC(ns[0], 46),
+UA_NODEID_NUMERIC(ns[0], 106LU),
+UA_NODEID_NUMERIC(ns[0], 72LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
UA_QUALIFIEDNAME(ns[0], "DataTypeVersion"),
-UA_NODEID_NUMERIC(ns[0], 68),
+UA_NODEID_NUMERIC(ns[0], 68LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
-retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 106), UA_NODEID_NUMERIC(ns[0], 37), UA_EXPANDEDNODEID_NUMERIC(ns[0], 80), true);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 106LU), UA_NODEID_NUMERIC(ns[0], 37LU), UA_EXPANDEDNODEID_NUMERIC(ns[0], 80LU), true);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_209_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_187_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 106)
+UA_NODEID_NUMERIC(ns[0], 106LU)
);
}
/* DataTypeDescriptionType - ns=0;i=69 */
-static UA_StatusCode function_namespace0_generated_210_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_188_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_VariableTypeAttributes attr = UA_VariableTypeAttributes_default;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 12);
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 12LU);
attr.displayName = UA_LOCALIZEDTEXT("", "DataTypeDescriptionType");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLETYPE,
-UA_NODEID_NUMERIC(ns[0], 69),
-UA_NODEID_NUMERIC(ns[0], 63),
-UA_NODEID_NUMERIC(ns[0], 45),
+UA_NODEID_NUMERIC(ns[0], 69LU),
+UA_NODEID_NUMERIC(ns[0], 63LU),
+UA_NODEID_NUMERIC(ns[0], 45LU),
UA_QUALIFIEDNAME(ns[0], "DataTypeDescriptionType"),
-UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_210_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_188_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 69)
+UA_NODEID_NUMERIC(ns[0], 69LU)
);
}
-/* DictionaryFragment - ns=0;i=105 */
+/* EnumValueType - ns=0;i=7656 */
-static UA_StatusCode function_namespace0_generated_211_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_189_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_VariableAttributes attr = UA_VariableAttributes_default;
attr.minimumSamplingInterval = 0.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 15);
-attr.displayName = UA_LOCALIZEDTEXT("", "DictionaryFragment");
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 12LU);
+UA_String *variablenode_ns_0_i_7656_variant_DataContents = UA_String_new();
+if (!variablenode_ns_0_i_7656_variant_DataContents) return UA_STATUSCODE_BADOUTOFMEMORY;
+UA_String_init(variablenode_ns_0_i_7656_variant_DataContents);
+*variablenode_ns_0_i_7656_variant_DataContents = UA_STRING_ALLOC("EnumValueType");
+UA_Variant_setScalar(&attr.value, variablenode_ns_0_i_7656_variant_DataContents, &UA_TYPES[UA_TYPES_STRING]);
+attr.displayName = UA_LOCALIZEDTEXT("", "EnumValueType");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 105),
-UA_NODEID_NUMERIC(ns[0], 69),
-UA_NODEID_NUMERIC(ns[0], 46),
-UA_QUALIFIEDNAME(ns[0], "DictionaryFragment"),
-UA_NODEID_NUMERIC(ns[0], 68),
+UA_NODEID_NUMERIC(ns[0], 7656LU),
+UA_NODEID_NUMERIC(ns[0], 7617LU),
+UA_NODEID_NUMERIC(ns[0], 47LU),
+UA_QUALIFIEDNAME(ns[0], "EnumValueType"),
+UA_NODEID_NUMERIC(ns[0], 69LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
-retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 105), UA_NODEID_NUMERIC(ns[0], 37), UA_EXPANDEDNODEID_NUMERIC(ns[0], 80), true);
+UA_String_delete(variablenode_ns_0_i_7656_variant_DataContents);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 7656LU), UA_NODEID_NUMERIC(ns[0], 39LU), UA_EXPANDEDNODEID_NUMERIC(ns[0], 8251LU), false);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_211_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_189_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 105)
+UA_NODEID_NUMERIC(ns[0], 7656LU)
);
}
-/* EnumValueType - ns=0;i=7656 */
+/* Argument - ns=0;i=7650 */
-static UA_StatusCode function_namespace0_generated_212_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_190_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_VariableAttributes attr = UA_VariableAttributes_default;
attr.minimumSamplingInterval = 0.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 12);
-UA_String *variablenode_ns_0_i_7656_variant_DataContents = UA_String_new();
-if (!variablenode_ns_0_i_7656_variant_DataContents) return UA_STATUSCODE_BADOUTOFMEMORY;
-UA_String_init(variablenode_ns_0_i_7656_variant_DataContents);
-*variablenode_ns_0_i_7656_variant_DataContents = UA_STRING_ALLOC("EnumValueType");
-UA_Variant_setScalar(&attr.value, variablenode_ns_0_i_7656_variant_DataContents, &UA_TYPES[UA_TYPES_STRING]);
-attr.displayName = UA_LOCALIZEDTEXT("", "EnumValueType");
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 12LU);
+UA_String *variablenode_ns_0_i_7650_variant_DataContents = UA_String_new();
+if (!variablenode_ns_0_i_7650_variant_DataContents) return UA_STATUSCODE_BADOUTOFMEMORY;
+UA_String_init(variablenode_ns_0_i_7650_variant_DataContents);
+*variablenode_ns_0_i_7650_variant_DataContents = UA_STRING_ALLOC("Argument");
+UA_Variant_setScalar(&attr.value, variablenode_ns_0_i_7650_variant_DataContents, &UA_TYPES[UA_TYPES_STRING]);
+attr.displayName = UA_LOCALIZEDTEXT("", "Argument");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 7656),
-UA_NODEID_NUMERIC(ns[0], 7617),
-UA_NODEID_NUMERIC(ns[0], 47),
-UA_QUALIFIEDNAME(ns[0], "EnumValueType"),
-UA_NODEID_NUMERIC(ns[0], 69),
+UA_NODEID_NUMERIC(ns[0], 7650LU),
+UA_NODEID_NUMERIC(ns[0], 7617LU),
+UA_NODEID_NUMERIC(ns[0], 47LU),
+UA_QUALIFIEDNAME(ns[0], "Argument"),
+UA_NODEID_NUMERIC(ns[0], 69LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
-UA_String_delete(variablenode_ns_0_i_7656_variant_DataContents);
-retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 7656), UA_NODEID_NUMERIC(ns[0], 39), UA_EXPANDEDNODEID_NUMERIC(ns[0], 8251), false);
+UA_String_delete(variablenode_ns_0_i_7650_variant_DataContents);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 7650LU), UA_NODEID_NUMERIC(ns[0], 39LU), UA_EXPANDEDNODEID_NUMERIC(ns[0], 298LU), false);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_212_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_190_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 7656)
+UA_NODEID_NUMERIC(ns[0], 7650LU)
);
}
-/* DataTypeVersion - ns=0;i=104 */
+/* DictionaryFragment - ns=0;i=105 */
-static UA_StatusCode function_namespace0_generated_213_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_191_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_VariableAttributes attr = UA_VariableAttributes_default;
attr.minimumSamplingInterval = 0.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 12);
-attr.displayName = UA_LOCALIZEDTEXT("", "DataTypeVersion");
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 15LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "DictionaryFragment");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 104),
-UA_NODEID_NUMERIC(ns[0], 69),
-UA_NODEID_NUMERIC(ns[0], 46),
-UA_QUALIFIEDNAME(ns[0], "DataTypeVersion"),
-UA_NODEID_NUMERIC(ns[0], 68),
+UA_NODEID_NUMERIC(ns[0], 105LU),
+UA_NODEID_NUMERIC(ns[0], 69LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
+UA_QUALIFIEDNAME(ns[0], "DictionaryFragment"),
+UA_NODEID_NUMERIC(ns[0], 68LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
-retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 104), UA_NODEID_NUMERIC(ns[0], 37), UA_EXPANDEDNODEID_NUMERIC(ns[0], 80), true);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 105LU), UA_NODEID_NUMERIC(ns[0], 37LU), UA_EXPANDEDNODEID_NUMERIC(ns[0], 80LU), true);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_213_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_191_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 104)
+UA_NODEID_NUMERIC(ns[0], 105LU)
);
}
-/* Argument - ns=0;i=7650 */
+/* DataTypeVersion - ns=0;i=104 */
-static UA_StatusCode function_namespace0_generated_214_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_192_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_VariableAttributes attr = UA_VariableAttributes_default;
attr.minimumSamplingInterval = 0.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
/* Value rank inherited */
-attr.valueRank = -1;
-attr.dataType = UA_NODEID_NUMERIC(ns[0], 12);
-UA_String *variablenode_ns_0_i_7650_variant_DataContents = UA_String_new();
-if (!variablenode_ns_0_i_7650_variant_DataContents) return UA_STATUSCODE_BADOUTOFMEMORY;
-UA_String_init(variablenode_ns_0_i_7650_variant_DataContents);
-*variablenode_ns_0_i_7650_variant_DataContents = UA_STRING_ALLOC("Argument");
-UA_Variant_setScalar(&attr.value, variablenode_ns_0_i_7650_variant_DataContents, &UA_TYPES[UA_TYPES_STRING]);
-attr.displayName = UA_LOCALIZEDTEXT("", "Argument");
+attr.valueRank = -2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 12LU);
+attr.displayName = UA_LOCALIZEDTEXT("", "DataTypeVersion");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
-UA_NODEID_NUMERIC(ns[0], 7650),
-UA_NODEID_NUMERIC(ns[0], 7617),
-UA_NODEID_NUMERIC(ns[0], 47),
-UA_QUALIFIEDNAME(ns[0], "Argument"),
-UA_NODEID_NUMERIC(ns[0], 69),
+UA_NODEID_NUMERIC(ns[0], 104LU),
+UA_NODEID_NUMERIC(ns[0], 69LU),
+UA_NODEID_NUMERIC(ns[0], 46LU),
+UA_QUALIFIEDNAME(ns[0], "DataTypeVersion"),
+UA_NODEID_NUMERIC(ns[0], 68LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
-UA_String_delete(variablenode_ns_0_i_7650_variant_DataContents);
-retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 7650), UA_NODEID_NUMERIC(ns[0], 39), UA_EXPANDEDNODEID_NUMERIC(ns[0], 298), false);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 104LU), UA_NODEID_NUMERIC(ns[0], 37LU), UA_EXPANDEDNODEID_NUMERIC(ns[0], 80LU), true);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_214_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_192_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 7650)
+UA_NODEID_NUMERIC(ns[0], 104LU)
);
}
/* Default XML - ns=0;i=3063 */
-static UA_StatusCode function_namespace0_generated_215_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_193_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_ObjectAttributes attr = UA_ObjectAttributes_default;
attr.displayName = UA_LOCALIZEDTEXT("", "Default XML");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECT,
-UA_NODEID_NUMERIC(ns[0], 3063),
-UA_NODEID_NUMERIC(ns[0], 0),
-UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 3063LU),
+UA_NODEID_NUMERIC(ns[0], 0LU),
+UA_NODEID_NUMERIC(ns[0], 0LU),
UA_QUALIFIEDNAME(ns[0], "Default XML"),
-UA_NODEID_NUMERIC(ns[0], 58),
+UA_NODEID_NUMERIC(ns[0], 58LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_215_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_193_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 3063)
+UA_NODEID_NUMERIC(ns[0], 3063LU)
);
}
/* Default Binary - ns=0;i=3062 */
-static UA_StatusCode function_namespace0_generated_216_begin(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_194_begin(UA_Server *server, UA_UInt16* ns) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_ObjectAttributes attr = UA_ObjectAttributes_default;
attr.displayName = UA_LOCALIZEDTEXT("", "Default Binary");
retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECT,
-UA_NODEID_NUMERIC(ns[0], 3062),
-UA_NODEID_NUMERIC(ns[0], 0),
-UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 3062LU),
+UA_NODEID_NUMERIC(ns[0], 0LU),
+UA_NODEID_NUMERIC(ns[0], 0LU),
UA_QUALIFIEDNAME(ns[0], "Default Binary"),
-UA_NODEID_NUMERIC(ns[0], 58),
+UA_NODEID_NUMERIC(ns[0], 58LU),
(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
return retVal;
}
-static UA_StatusCode function_namespace0_generated_216_finish(UA_Server *server, UA_UInt16* ns) {
+static UA_StatusCode function_namespace0_generated_194_finish(UA_Server *server, UA_UInt16* ns) {
return UA_Server_addNode_finish(server,
-UA_NODEID_NUMERIC(ns[0], 3062)
+UA_NODEID_NUMERIC(ns[0], 3062LU)
);
}
@@ -52031,451 +57143,407 @@ UA_StatusCode retVal = UA_STATUSCODE_GOOD;
/* Use namespace ids generated by the server */
UA_UInt16 ns[1];
ns[0] = UA_Server_addNamespace(server, "http://opcfoundation.org/UA/");
-bool dummy = (
-!(retVal = function_namespace0_generated_0_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_1_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_2_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_3_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_4_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_5_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_6_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_7_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_8_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_9_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_10_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_11_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_12_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_13_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_14_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_15_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_16_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_17_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_18_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_19_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_20_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_21_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_22_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_23_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_24_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_25_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_26_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_27_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_28_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_29_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_30_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_31_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_32_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_33_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_34_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_35_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_36_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_37_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_38_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_39_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_40_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_41_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_42_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_43_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_44_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_45_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_46_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_47_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_48_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_49_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_50_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_51_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_52_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_53_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_54_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_55_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_56_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_57_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_58_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_59_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_60_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_61_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_62_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_63_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_64_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_65_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_66_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_67_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_68_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_69_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_70_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_71_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_72_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_73_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_74_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_75_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_76_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_77_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_78_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_79_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_80_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_81_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_82_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_83_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_84_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_85_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_86_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_87_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_88_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_89_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_90_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_91_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_92_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_93_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_94_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_95_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_96_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_97_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_98_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_99_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_100_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_101_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_102_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_103_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_104_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_105_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_106_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_107_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_108_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_109_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_110_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_111_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_112_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_113_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_114_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_115_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_116_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_117_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_118_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_119_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_120_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_121_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_122_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_123_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_124_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_125_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_126_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_127_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_128_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_129_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_130_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_131_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_132_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_133_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_134_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_135_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_136_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_137_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_138_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_139_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_140_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_141_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_142_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_143_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_144_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_145_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_146_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_147_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_148_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_149_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_150_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_151_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_152_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_153_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_154_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_155_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_156_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_157_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_158_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_159_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_160_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_161_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_162_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_163_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_164_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_165_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_166_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_167_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_168_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_169_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_170_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_171_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_172_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_173_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_174_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_175_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_176_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_177_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_178_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_179_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_180_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_181_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_182_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_183_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_184_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_185_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_186_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_187_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_188_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_189_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_190_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_191_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_192_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_193_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_194_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_195_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_196_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_197_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_198_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_199_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_200_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_201_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_202_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_203_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_204_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_205_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_206_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_207_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_208_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_209_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_210_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_211_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_212_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_213_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_214_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_215_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_216_begin(server, ns)) &&
-!(retVal = function_namespace0_generated_216_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_215_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_214_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_213_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_212_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_211_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_210_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_209_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_208_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_207_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_206_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_205_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_204_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_203_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_202_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_201_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_200_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_199_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_198_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_197_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_196_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_195_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_194_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_193_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_192_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_191_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_190_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_189_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_188_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_187_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_186_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_185_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_184_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_183_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_182_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_181_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_180_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_179_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_178_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_177_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_176_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_175_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_174_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_173_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_172_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_171_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_170_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_169_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_168_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_167_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_166_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_165_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_164_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_163_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_162_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_161_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_160_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_159_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_158_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_157_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_156_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_155_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_154_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_153_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_152_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_151_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_150_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_149_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_148_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_147_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_146_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_145_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_144_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_143_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_142_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_141_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_140_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_139_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_138_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_137_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_136_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_135_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_134_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_133_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_132_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_131_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_130_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_129_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_128_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_127_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_126_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_125_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_124_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_123_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_122_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_121_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_120_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_119_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_118_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_117_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_116_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_115_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_114_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_113_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_112_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_111_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_110_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_109_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_108_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_107_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_106_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_105_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_104_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_103_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_102_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_101_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_100_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_99_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_98_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_97_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_96_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_95_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_94_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_93_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_92_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_91_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_90_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_89_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_88_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_87_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_86_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_85_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_84_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_83_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_82_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_81_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_80_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_79_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_78_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_77_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_76_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_75_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_74_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_73_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_72_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_71_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_70_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_69_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_68_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_67_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_66_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_65_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_64_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_63_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_62_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_61_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_60_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_59_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_58_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_57_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_56_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_55_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_54_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_53_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_52_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_51_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_50_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_49_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_48_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_47_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_46_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_45_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_44_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_43_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_42_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_41_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_40_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_39_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_38_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_37_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_36_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_35_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_34_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_33_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_32_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_31_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_30_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_29_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_28_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_27_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_26_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_25_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_24_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_23_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_22_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_21_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_20_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_19_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_18_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_17_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_16_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_15_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_14_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_13_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_12_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_11_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_10_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_9_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_8_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_7_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_6_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_5_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_4_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_3_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_2_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_1_finish(server, ns)) &&
-!(retVal = function_namespace0_generated_0_finish(server, ns))
-); (void)(dummy);
+
+/* Load custom datatype definitions into the server */
+if((retVal = function_namespace0_generated_0_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_0_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_1_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_1_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_2_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_2_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_3_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_3_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_4_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_4_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_5_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_5_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_6_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_7_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_8_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_9_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_10_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_11_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_12_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_13_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_14_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_15_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_16_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_17_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_18_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_19_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_20_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_21_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_22_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_23_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_24_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_25_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_26_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_27_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_28_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_29_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_30_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_31_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_32_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_33_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_34_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_35_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_36_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_37_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_38_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_39_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_40_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_41_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_42_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_43_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_44_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_45_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_46_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_47_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_48_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_49_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_50_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_51_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_52_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_53_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_54_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_55_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_56_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_57_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_58_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_59_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_60_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_61_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_62_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_63_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_64_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_65_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_66_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_67_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_68_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_69_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_70_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_71_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_72_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_73_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_74_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_75_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_76_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_77_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_78_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_79_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_80_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_81_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_82_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_83_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_84_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_85_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_86_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_87_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_88_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_89_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_90_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_91_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_92_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_93_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_94_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_95_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_96_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_97_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_98_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_99_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_100_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_101_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_102_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_103_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_104_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_105_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_106_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_107_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_108_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_109_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_110_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_111_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_112_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_113_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_114_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_115_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_116_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_117_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_118_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_119_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_120_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_121_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_122_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_123_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_124_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_125_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_126_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_127_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_128_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_129_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_130_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_131_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_132_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_133_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_134_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_135_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_136_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_137_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_138_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_139_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_140_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_141_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_142_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_143_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_144_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_145_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_146_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_147_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_148_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_149_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_150_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_151_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_152_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_153_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_154_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_155_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_156_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_157_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_158_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_159_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_160_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_161_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_162_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_163_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_164_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_165_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_166_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_167_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_168_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_169_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_170_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_171_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_172_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_173_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_174_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_175_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_176_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_177_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_178_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_179_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_180_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_181_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_182_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_183_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_184_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_185_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_186_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_187_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_188_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_189_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_190_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_191_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_192_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_193_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_194_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_194_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_193_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_192_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_191_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_190_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_189_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_188_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_187_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_186_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_185_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_184_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_183_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_182_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_181_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_180_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_179_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_178_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_177_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_176_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_175_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_174_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_173_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_172_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_171_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_170_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_169_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_168_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_167_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_166_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_165_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_164_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_163_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_162_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_161_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_160_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_159_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_158_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_157_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_156_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_155_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_154_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_153_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_152_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_151_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_150_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_149_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_148_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_147_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_146_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_145_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_144_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_143_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_142_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_141_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_140_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_139_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_138_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_137_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_136_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_135_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_134_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_133_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_132_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_131_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_130_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_129_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_128_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_127_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_126_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_125_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_124_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_123_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_122_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_121_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_120_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_119_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_118_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_117_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_116_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_115_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_114_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_113_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_112_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_111_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_110_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_109_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_108_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_107_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_106_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_105_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_104_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_103_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_102_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_101_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_100_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_99_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_98_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_97_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_96_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_95_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_94_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_93_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_92_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_91_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_90_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_89_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_88_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_87_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_86_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_85_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_84_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_83_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_82_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_81_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_80_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_79_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_78_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_77_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_76_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_75_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_74_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_73_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_72_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_71_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_70_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_69_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_68_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_67_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_66_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_65_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_64_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_63_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_62_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_61_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_60_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_59_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_58_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_57_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_56_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_55_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_54_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_53_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_52_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_51_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_50_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_49_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_48_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_47_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_46_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_45_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_44_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_43_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_42_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_41_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_40_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_39_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_38_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_37_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_36_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_35_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_34_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_33_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_32_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_31_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_30_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_29_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_28_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_27_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_26_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_25_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_24_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_23_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_22_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_21_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_20_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_19_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_18_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_17_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_16_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_15_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_14_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_13_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_12_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_11_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_10_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_9_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_8_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_7_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
+if((retVal = function_namespace0_generated_6_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
return retVal;
}
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/src/ua_types_lex.c" ***********************************/
+/**** amalgamated original file "/src/ua_types_lex.c" ****/
/* Generated by re2c 1.1.1 */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Copyright 2020 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
*
@@ -52602,7 +57670,7 @@ parse_nodeid(UA_NodeId *id, const char *pos, const char *end) {
memset(&context, 0, sizeof(LexContext));
const char *ns = NULL, *nse= NULL;
-
+
{
char yych;
yych = YYPEEK ();
@@ -52737,7 +57805,7 @@ parse_expandednodeid(UA_ExpandedNodeId *id, const char *pos, const char *end) {
memset(&context, 0, sizeof(LexContext));
const char *svr = NULL, *svre = NULL, *nsu = NULL, *ns = NULL, *body = NULL;
-
+
{
char yych;
yych = YYPEEK ();
@@ -53040,7 +58108,7 @@ parse_refpath_qn_name(UA_QualifiedName *qn, const char **pos, const char *end) {
size_t maxlen = (size_t)(end - *pos);
if(maxlen == 0) {
qn->name.data = (UA_Byte*)UA_EMPTY_ARRAY_SENTINEL;
- return UA_STATUSCODE_GOOD;;
+ return UA_STATUSCODE_GOOD;
}
char *name = (char*)UA_malloc(maxlen);
if(!name)
@@ -53088,7 +58156,7 @@ parse_refpath_qn(UA_QualifiedName *qn, const char *pos, const char *end) {
const char *ns = NULL, *nse = NULL;
UA_QualifiedName_init(qn);
-
+
{
char yych;
yych = YYPEEK ();
@@ -53230,7 +58298,7 @@ parse_relativepath(UA_RelativePath *rp, const char *pos, const char *end) {
current.includeSubtypes = true; /* Follow subtypes by default */
/* Get the ReferenceType and its modifiers */
-
+
{
char yych;
unsigned int yyaccept = 0;
@@ -53346,7 +58414,7 @@ yy71:
if(res != UA_STATUSCODE_GOOD)
return res;
-
+
{
char yych;
yych = YYPEEK ();
@@ -53412,7 +58480,7 @@ UA_RelativePath_parse(UA_RelativePath *rp, const UA_String str) {
return res;
}
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/src/server/ua_subscription.c" ***********************************/
+/**** amalgamated original file "/src/server/ua_subscription.c" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -53436,45 +58504,82 @@ UA_RelativePath_parse(UA_RelativePath *rp, const UA_String str) {
#ifdef UA_ENABLE_SUBSCRIPTIONS /* conditional compilation */
+#define UA_MAX_RETRANSMISSIONQUEUESIZE 256
+
UA_Subscription *
-UA_Subscription_new(UA_Session *session, UA_UInt32 subscriptionId) {
+UA_Subscription_new(void) {
/* Allocate the memory */
- UA_Subscription *newSub =
- (UA_Subscription*)UA_calloc(1, sizeof(UA_Subscription));
+ UA_Subscription *newSub = (UA_Subscription*)UA_calloc(1, sizeof(UA_Subscription));
if(!newSub)
return NULL;
- /* Remaining members are covered by calloc zeroing out the memory */
- newSub->session = session;
- newSub->subscriptionId = subscriptionId;
- newSub->state = UA_SUBSCRIPTIONSTATE_NORMAL; /* The first publish response is sent immediately */
+ /* The first publish response is sent immediately */
+ newSub->state = UA_SUBSCRIPTIONSTATE_NORMAL;
+
/* Even if the first publish response is a keepalive the sequence number is 1.
* This can happen by a subscription without a monitored item (see CTT test scripts). */
newSub->nextSequenceNumber = 1;
+
TAILQ_INIT(&newSub->retransmissionQueue);
TAILQ_INIT(&newSub->notificationQueue);
return newSub;
}
void
-UA_Subscription_deleteMembers(UA_Server *server, UA_Subscription *sub) {
- UA_LOCK_ASSERT(server->serviceMutex, 1);
+UA_Subscription_delete(UA_Server *server, UA_Subscription *sub) {
+ UA_LOCK_ASSERT(&server->serviceMutex, 1);
+ /* Unregister the publish callback */
Subscription_unregisterPublishCallback(server, sub);
+ /* Remove the diagnostics object for the subscription */
+#ifdef UA_ENABLE_DIAGNOSTICS
+ if(sub->session) {
+ /* Use a browse path to find the node */
+ char subIdStr[32];
+ snprintf(subIdStr, 32, "%u", sub->subscriptionId);
+ UA_BrowsePath bp;
+ UA_BrowsePath_init(&bp);
+ bp.startingNode = sub->session->sessionId;
+ UA_RelativePathElement rpe[2];
+ memset(rpe, 0, sizeof(UA_RelativePathElement) * 2);
+ rpe[0].targetName = UA_QUALIFIEDNAME(0, "SubscriptionDiagnosticsArray");
+ rpe[1].targetName = UA_QUALIFIEDNAME(0, subIdStr);
+ bp.relativePath.elements = rpe;
+ bp.relativePath.elementsSize = 2;
+ UA_BrowsePathResult bpr = translateBrowsePathToNodeIds(server, &bp);
+
+ /* Delete all nodes matching the browse path */
+ for(size_t i = 0; i < bpr.targetsSize; i++) {
+ if(bpr.targets[i].remainingPathIndex < UA_UINT32_MAX)
+ continue;
+ deleteNode(server, bpr.targets[i].targetId.nodeId, true);
+ }
+ UA_BrowsePathResult_clear(&bpr);
+ }
+#endif
+
+ UA_LOG_INFO_SUBSCRIPTION(&server->config.logger, sub, "Subscription deleted");
+
+ /* Detach from the session if necessary */
+ if(sub->session)
+ UA_Session_detachSubscription(server, sub->session, sub, true);
+
+ /* Remove from the server if not previously registered */
+ if(sub->serverListEntry.le_prev) {
+ LIST_REMOVE(sub, serverListEntry);
+ UA_assert(server->subscriptionsSize > 0);
+ server->subscriptionsSize--;
+ server->serverDiagnosticsSummary.currentSubscriptionCount--;
+ }
+
/* Delete monitored Items */
+ UA_assert(server->monitoredItemsSize >= sub->monitoredItemsSize);
UA_MonitoredItem *mon, *tmp_mon;
LIST_FOREACH_SAFE(mon, &sub->monitoredItems, listEntry, tmp_mon) {
- LIST_REMOVE(mon, listEntry);
- UA_LOG_INFO_SESSION(&server->config.logger, sub->session,
- "Subscription %" PRIu32 " | MonitoredItem %" PRIi32 " | "
- "Deleted the MonitoredItem", sub->subscriptionId,
- mon->monitoredItemId);
UA_MonitoredItem_delete(server, mon);
}
- UA_assert(server->numMonitoredItems >= sub->monitoredItemsSize);
- server->numMonitoredItems -= sub->monitoredItemsSize;
- sub->monitoredItemsSize = 0;
+ UA_assert(sub->monitoredItemsSize == 0);
/* Delete Retransmission Queue */
UA_NotificationMessageEntry *nme, *nme_tmp;
@@ -53482,14 +58587,21 @@ UA_Subscription_deleteMembers(UA_Server *server, UA_Subscription *sub) {
TAILQ_REMOVE(&sub->retransmissionQueue, nme, listEntry);
UA_NotificationMessage_clear(&nme->message);
UA_free(nme);
- --sub->session->totalRetransmissionQueueSize;
+ if(sub->session)
+ --sub->session->totalRetransmissionQueueSize;
--sub->retransmissionQueueSize;
}
UA_assert(sub->retransmissionQueueSize == 0);
- UA_LOG_INFO_SESSION(&server->config.logger, sub->session,
- "Subscription %" PRIu32 " | Deleted the Subscription",
- sub->subscriptionId);
+ /* Add a delayed callback to remove the Subscription when the current jobs
+ * have completed. Pointers to the subscription may still exist upwards in
+ * the call stack. */
+ sub->delayedFreePointers.callback = NULL;
+ sub->delayedFreePointers.application = server;
+ sub->delayedFreePointers.data = NULL;
+ sub->delayedFreePointers.nextTime = UA_DateTime_nowMonotonic() + 1;
+ sub->delayedFreePointers.interval = 0; /* Remove the structure */
+ UA_Timer_addTimerEntry(&server->timer, &sub->delayedFreePointers, NULL);
}
UA_MonitoredItem *
@@ -53502,54 +58614,30 @@ UA_Subscription_getMonitoredItem(UA_Subscription *sub, UA_UInt32 monitoredItemId
return mon;
}
-UA_StatusCode
-UA_Subscription_deleteMonitoredItem(UA_Server *server, UA_Subscription *sub,
- UA_UInt32 monitoredItemId) {
- UA_LOCK_ASSERT(server->serviceMutex, 1);
-
- /* Find the MonitoredItem */
- UA_MonitoredItem *mon;
- LIST_FOREACH(mon, &sub->monitoredItems, listEntry) {
- if(mon->monitoredItemId == monitoredItemId)
- break;
- }
- if(!mon)
- return UA_STATUSCODE_BADMONITOREDITEMIDINVALID;
-
- UA_LOG_INFO_SESSION(&server->config.logger, sub->session,
- "Subscription %" PRIu32 " | MonitoredItem %" PRIi32 " | "
- "Delete the MonitoredItem", sub->subscriptionId,
- mon->monitoredItemId);
-
- /* Remove the MonitoredItem */
- LIST_REMOVE(mon, listEntry);
- UA_assert(sub->monitoredItemsSize > 0);
- UA_assert(server->numMonitoredItems > 0);
- sub->monitoredItemsSize--;
- server->numMonitoredItems--;
-
- /* Remove content and delayed free */
- UA_MonitoredItem_delete(server, mon);
-
- return UA_STATUSCODE_GOOD;
-}
+static void
+removeOldestRetransmissionMessageFromSub(UA_Subscription *sub) {
+ UA_NotificationMessageEntry *oldestEntry =
+ TAILQ_LAST(&sub->retransmissionQueue, NotificationMessageQueue);
+ TAILQ_REMOVE(&sub->retransmissionQueue, oldestEntry, listEntry);
+ UA_NotificationMessage_clear(&oldestEntry->message);
+ UA_free(oldestEntry);
+ --sub->retransmissionQueueSize;
+ if(sub->session)
+ --sub->session->totalRetransmissionQueueSize;
-void
-UA_Subscription_addMonitoredItem(UA_Server *server, UA_Subscription *sub, UA_MonitoredItem *newMon) {
- sub->monitoredItemsSize++;
- server->numMonitoredItems++;
- LIST_INSERT_HEAD(&sub->monitoredItems, newMon, listEntry);
+#ifdef UA_ENABLE_DIAGNOSTICS
+ sub->discardedMessageCount++;
+#endif
}
static void
-removeOldestRetransmissionMessage(UA_Session *session) {
+removeOldestRetransmissionMessageFromSession(UA_Session *session) {
UA_NotificationMessageEntry *oldestEntry = NULL;
UA_Subscription *oldestSub = NULL;
-
UA_Subscription *sub;
- LIST_FOREACH(sub, &session->serverSubscriptions, listEntry) {
+ TAILQ_FOREACH(sub, &session->subscriptions, sessionListEntry) {
UA_NotificationMessageEntry *first =
- TAILQ_LAST(&sub->retransmissionQueue, ListOfNotificationMessages);
+ TAILQ_LAST(&sub->retransmissionQueue, NotificationMessageQueue);
if(!first)
continue;
if(!oldestEntry || oldestEntry->message.publishTime > first->message.publishTime) {
@@ -53560,28 +58648,31 @@ removeOldestRetransmissionMessage(UA_Session *session) {
UA_assert(oldestEntry);
UA_assert(oldestSub);
- TAILQ_REMOVE(&oldestSub->retransmissionQueue, oldestEntry, listEntry);
- UA_NotificationMessage_clear(&oldestEntry->message);
- UA_free(oldestEntry);
- --session->totalRetransmissionQueueSize;
- --oldestSub->retransmissionQueueSize;
+ removeOldestRetransmissionMessageFromSub(oldestSub);
}
static void
UA_Subscription_addRetransmissionMessage(UA_Server *server, UA_Subscription *sub,
UA_NotificationMessageEntry *entry) {
/* Release the oldest entry if there is not enough space */
- if(server->config.maxRetransmissionQueueSize > 0 &&
- sub->session->totalRetransmissionQueueSize >= server->config.maxRetransmissionQueueSize) {
- UA_LOG_WARNING_SESSION(&server->config.logger, sub->session, "Subscription %" PRIu32 " | "
- "Retransmission queue overflow", sub->subscriptionId);
- removeOldestRetransmissionMessage(sub->session);
+ UA_Session *session = sub->session;
+ if(sub->retransmissionQueueSize >= UA_MAX_RETRANSMISSIONQUEUESIZE) {
+ UA_LOG_WARNING_SUBSCRIPTION(&server->config.logger, sub,
+ "Subscription retransmission queue overflow");
+ removeOldestRetransmissionMessageFromSub(sub);
+ } else if(session && server->config.maxRetransmissionQueueSize > 0 &&
+ session->totalRetransmissionQueueSize >=
+ server->config.maxRetransmissionQueueSize) {
+ UA_LOG_WARNING_SUBSCRIPTION(&server->config.logger, sub,
+ "Session-wide retransmission queue overflow");
+ removeOldestRetransmissionMessageFromSession(sub->session);
}
/* Add entry */
TAILQ_INSERT_TAIL(&sub->retransmissionQueue, entry, listEntry);
- ++sub->session->totalRetransmissionQueueSize;
++sub->retransmissionQueueSize;
+ if(session)
+ ++session->totalRetransmissionQueueSize;
}
UA_StatusCode
@@ -53597,19 +58688,29 @@ UA_Subscription_removeRetransmissionMessage(UA_Subscription *sub, UA_UInt32 sequ
/* Remove the retransmission message */
TAILQ_REMOVE(&sub->retransmissionQueue, entry, listEntry);
- --sub->session->totalRetransmissionQueueSize;
--sub->retransmissionQueueSize;
UA_NotificationMessage_clear(&entry->message);
UA_free(entry);
+
+ if(sub->session)
+ --sub->session->totalRetransmissionQueueSize;
+
return UA_STATUSCODE_GOOD;
}
+/* The output counters are only set when the preparation is successful */
static UA_StatusCode
prepareNotificationMessage(UA_Server *server, UA_Subscription *sub,
- UA_NotificationMessage *message, size_t notifications) {
- UA_assert(notifications > 0);
+ UA_NotificationMessage *message,
+ size_t maxNotifications) {
+ UA_assert(maxNotifications > 0);
- /* Allocate an ExtensionObject for events and data */
+ /* Allocate an ExtensionObject for Event- and DataChange-Notifications. Also
+ * there can be StatusChange-Notifications. The standard says in Part 4,
+ * 7.2.1:
+ *
+ * If a Subscription contains MonitoredItems for events and data, this array
+ * should have not more than 2 elements. */
message->notificationData = (UA_ExtensionObject*)
UA_Array_new(2, &UA_TYPES[UA_TYPES_EXTENSIONOBJECT]);
if(!message->notificationData)
@@ -53618,6 +58719,7 @@ prepareNotificationMessage(UA_Server *server, UA_Subscription *sub,
/* Pre-allocate DataChangeNotifications */
size_t notificationDataIdx = 0;
+ size_t dcnPos = 0; /* How many DataChangeNotifications? */
UA_DataChangeNotification *dcn = NULL;
if(sub->dataChangeNotifications > 0) {
dcn = UA_DataChangeNotification_new();
@@ -53625,13 +58727,11 @@ prepareNotificationMessage(UA_Server *server, UA_Subscription *sub,
UA_NotificationMessage_clear(message);
return UA_STATUSCODE_BADOUTOFMEMORY;
}
- message->notificationData->encoding = UA_EXTENSIONOBJECT_DECODED;
- message->notificationData->content.decoded.data = dcn;
- message->notificationData->content.decoded.type = &UA_TYPES[UA_TYPES_DATACHANGENOTIFICATION];
-
+ UA_ExtensionObject_setValue(message->notificationData, dcn,
+ &UA_TYPES[UA_TYPES_DATACHANGENOTIFICATION]);
size_t dcnSize = sub->dataChangeNotifications;
- if(dcnSize > notifications)
- dcnSize = notifications;
+ if(dcnSize > maxNotifications)
+ dcnSize = maxNotifications;
dcn->monitoredItems = (UA_MonitoredItemNotification*)
UA_Array_new(dcnSize, &UA_TYPES[UA_TYPES_MONITOREDITEMNOTIFICATION]);
if(!dcn->monitoredItems) {
@@ -53643,34 +58743,21 @@ prepareNotificationMessage(UA_Server *server, UA_Subscription *sub,
}
#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
+ size_t enlPos = 0; /* How many EventNotifications? */
UA_EventNotificationList *enl = NULL;
- UA_StatusChangeNotification *scn = NULL;
- /* Pre-allocate either StatusChange or EventNotifications. Sending a
- * (single) StatusChangeNotification has priority. */
- if(sub->statusChangeNotifications > 0) {
- scn = UA_StatusChangeNotification_new();
- if(!scn) {
- UA_NotificationMessage_clear(message);
- return UA_STATUSCODE_BADOUTOFMEMORY;
- }
- message->notificationData[notificationDataIdx].encoding = UA_EXTENSIONOBJECT_DECODED;
- message->notificationData[notificationDataIdx].content.decoded.data = scn;
- message->notificationData[notificationDataIdx].content.decoded.type = &UA_TYPES[UA_TYPES_STATUSCHANGENOTIFICATION];
- notificationDataIdx++;
- } else if(sub->eventNotifications > 0) {
+ if(sub->eventNotifications > 0) {
enl = UA_EventNotificationList_new();
if(!enl) {
UA_NotificationMessage_clear(message);
return UA_STATUSCODE_BADOUTOFMEMORY;
}
- message->notificationData[notificationDataIdx].encoding = UA_EXTENSIONOBJECT_DECODED;
- message->notificationData[notificationDataIdx].content.decoded.data = enl;
- message->notificationData[notificationDataIdx].content.decoded.type = &UA_TYPES[UA_TYPES_EVENTNOTIFICATIONLIST];
-
+ UA_ExtensionObject_setValue(&message->notificationData[notificationDataIdx],
+ enl, &UA_TYPES[UA_TYPES_EVENTNOTIFICATIONLIST]);
size_t enlSize = sub->eventNotifications;
- if(enlSize > notifications)
- enlSize = notifications;
- enl->events = (UA_EventFieldList*) UA_Array_new(enlSize, &UA_TYPES[UA_TYPES_EVENTFIELDLIST]);
+ if(enlSize > maxNotifications)
+ enlSize = maxNotifications;
+ enl->events = (UA_EventFieldList*)
+ UA_Array_new(enlSize, &UA_TYPES[UA_TYPES_EVENTFIELDLIST]);
if(!enl->events) {
UA_NotificationMessage_clear(message);
return UA_STATUSCODE_BADOUTOFMEMORY;
@@ -53685,47 +58772,44 @@ prepareNotificationMessage(UA_Server *server, UA_Subscription *sub,
/* <-- The point of no return --> */
- size_t totalNotifications = 0; /* How many notifications were moved to the response overall? */
- size_t dcnPos = 0; /* How many DataChangeNotifications were put into the list? */
-#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
- size_t enlPos = 0; /* How many EventNotifications were moved into the list */
-#endif
+ /* How many notifications were moved to the response overall? */
+ size_t totalNotifications = 0;
UA_Notification *notification, *notification_tmp;
- TAILQ_FOREACH_SAFE(notification, &sub->notificationQueue, globalEntry, notification_tmp) {
- if(totalNotifications >= notifications)
+ TAILQ_FOREACH_SAFE(notification, &sub->notificationQueue,
+ globalEntry, notification_tmp) {
+ if(totalNotifications >= maxNotifications)
break;
- UA_MonitoredItem *mon = notification->mon;
-
- /* Remove from the queues and decrease the counters */
- UA_Notification_dequeue(server, notification);
-
/* Move the content to the response */
+ switch(notification->mon->itemToMonitor.attributeId) {
#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
- if(mon->attributeId == UA_ATTRIBUTEID_EVENTNOTIFIER) {
-
+ case UA_ATTRIBUTEID_EVENTNOTIFIER:
UA_assert(enl != NULL); /* Have at least one event notification */
-
- /* Move the content to the response */
- UA_EventFieldList *efl = &enl->events[enlPos];
- *efl = notification->data.event.fields;
- UA_EventFieldList_init(&notification->data.event.fields);
- efl->clientHandle = mon->clientHandle;
-
+ enl->events[enlPos] = notification->data.event;
+ UA_EventFieldList_init(&notification->data.event);
enlPos++;
- } else
+ break;
#endif
- {
+ default:
UA_assert(dcn != NULL); /* Have at least one change notification */
- /* Move the content to the response */
- UA_MonitoredItemNotification *min = &dcn->monitoredItems[dcnPos];
- min->clientHandle = mon->clientHandle;
- min->value = notification->data.value;
- UA_DataValue_init(&notification->data.value); /* Reset after the value has been moved */
+ dcn->monitoredItems[dcnPos] = notification->data.dataChange;
+ UA_DataValue_init(&notification->data.dataChange.value);
dcnPos++;
+ break;
+ }
+
+ /* If there are Notifications *before this one* in the MonitoredItem-
+ * local queue, remove all of them. These are earlier Notifications that
+ * are non-reporting. And we don't want them to show up after the
+ * current Notification has been sent out. */
+ UA_Notification *prev;
+ while((prev = TAILQ_PREV(notification, NotificationQueue, localEntry))) {
+ UA_Notification_delete(prev);
}
+ /* Delete the notification, remove from the queues and decrease the counters */
UA_Notification_delete(notification);
+
totalNotifications++;
}
@@ -53763,52 +58847,109 @@ UA_Subscription_nextSequenceNumber(UA_UInt32 sequenceNumber) {
static void
publishCallback(UA_Server *server, UA_Subscription *sub) {
- sub->readyNotifications = sub->notificationQueueSize;
- UA_LOCK(server->serviceMutex);
+ UA_LOCK(&server->serviceMutex);
UA_Subscription_publish(server, sub);
- UA_UNLOCK(server->serviceMutex);
+ UA_UNLOCK(&server->serviceMutex);
+}
+
+static void
+sendStatusChangeDelete(UA_Server *server, UA_Subscription *sub,
+ UA_PublishResponseEntry *pre) {
+ /* Cannot send out the StatusChange because no response is queued.
+ * Delete the Subscription without sending the StatusChange. */
+ if(!pre) {
+ UA_LOG_DEBUG_SUBSCRIPTION(&server->config.logger, sub,
+ "Cannot send the StatusChange notification. "
+ "Removing the subscription.");
+ UA_Subscription_delete(server, sub);
+ return;
+ }
+
+ UA_LOG_DEBUG_SUBSCRIPTION(&server->config.logger, sub,
+ "Sending out a StatusChange "
+ "notification and removing the subscription");
+
+ /* Populate the response */
+ UA_PublishResponse *response = &pre->response;
+
+ UA_StatusChangeNotification scn;
+ UA_StatusChangeNotification_init(&scn);
+ scn.status = sub->statusChange;
+
+ UA_ExtensionObject notificationData;
+ UA_ExtensionObject_setValue(&notificationData, &scn,
+ &UA_TYPES[UA_TYPES_STATUSCHANGENOTIFICATION]);
+
+ response->responseHeader.timestamp = UA_DateTime_now();
+ response->notificationMessage.notificationData = &notificationData;
+ response->notificationMessage.notificationDataSize = 1;
+ response->subscriptionId = sub->subscriptionId;
+ response->notificationMessage.publishTime = response->responseHeader.timestamp;
+ response->notificationMessage.sequenceNumber = sub->nextSequenceNumber;
+
+ /* Send the response */
+ UA_assert(sub->session); /* Otherwise pre is NULL */
+ UA_LOG_DEBUG_SUBSCRIPTION(&server->config.logger, sub,
+ "Sending out a publish response");
+ sendResponse(server, sub->session, sub->session->header.channel, pre->requestId,
+ (UA_Response *)response, &UA_TYPES[UA_TYPES_PUBLISHRESPONSE]);
+
+ /* Clean up */
+ response->notificationMessage.notificationData = NULL;
+ response->notificationMessage.notificationDataSize = 0;
+ UA_PublishResponse_clear(&pre->response);
+ UA_free(pre);
+
+ /* Delete the subscription */
+ UA_Subscription_delete(server, sub);
+}
+
+/* Called every time we set the subscription late (or it is still late) */
+static void
+UA_Subscription_isLate(UA_Subscription *sub) {
+ sub->state = UA_SUBSCRIPTIONSTATE_LATE;
+#ifdef UA_ENABLE_DIAGNOSTICS
+ sub->latePublishRequestCount++;
+#endif
}
void
UA_Subscription_publish(UA_Server *server, UA_Subscription *sub) {
- UA_LOCK_ASSERT(server->serviceMutex, 1);
+ UA_LOCK_ASSERT(&server->serviceMutex, 1);
+ UA_LOG_DEBUG_SUBSCRIPTION(&server->config.logger, sub, "Publish Callback");
+ UA_assert(sub);
- UA_LOG_DEBUG_SESSION(&server->config.logger, sub->session, "Subscription %" PRIu32 " | "
- "Publish Callback", sub->subscriptionId);
/* Dequeue a response */
- UA_PublishResponseEntry *pre = UA_Session_dequeuePublishReq(sub->session);
+ UA_PublishResponseEntry *pre = NULL;
+ if(sub->session)
+ pre = UA_Session_dequeuePublishReq(sub->session);
+
+ /* Update the LifetimeCounter */
if(pre) {
- sub->currentLifetimeCount = 0; /* Reset the LifetimeCounter */
+ sub->currentLifetimeCount = 0;
} else {
- UA_LOG_DEBUG_SESSION(&server->config.logger, sub->session,
- "Subscription %" PRIu32 " | The publish queue is empty",
- sub->subscriptionId);
+ UA_LOG_DEBUG_SUBSCRIPTION(&server->config.logger, sub,
+ "The publish queue is empty");
++sub->currentLifetimeCount;
-
if(sub->currentLifetimeCount > sub->lifeTimeCount) {
- UA_LOG_DEBUG_SESSION(&server->config.logger, sub->session,
- "Subscription %" PRIu32 " | End of lifetime "
- "for subscription", sub->subscriptionId);
- UA_Session_deleteSubscription(server, sub->session, sub->subscriptionId);
- /* TODO: send a StatusChangeNotification with Bad_Timeout */
- return;
+ UA_LOG_WARNING_SUBSCRIPTION(&server->config.logger, sub,
+ "End of subscription lifetime");
+ /* Set the StatusChange to delete the subscription. */
+ sub->statusChange = UA_STATUSCODE_BADTIMEOUT;
}
}
- /* If there are several late publish responses... */
- if(sub->readyNotifications > sub->notificationQueueSize)
- sub->readyNotifications = sub->notificationQueueSize;
+ /* Send a StatusChange notification if possible and delete the
+ * Subscription */
+ if(sub->statusChange != UA_STATUSCODE_GOOD) {
+ sendStatusChangeDelete(server, sub, pre);
+ return;
+ }
/* Count the available notifications */
- UA_UInt32 notifications = sub->readyNotifications;
- if(!sub->publishingEnabled)
- notifications = 0;
-
- UA_Boolean moreNotifications = false;
- if(notifications > sub->notificationsPerPublish) {
+ UA_UInt32 notifications = (sub->publishingEnabled) ? sub->notificationQueueSize : 0;
+ if(notifications > sub->notificationsPerPublish)
notifications = sub->notificationsPerPublish;
- moreNotifications = true;
- }
/* Return if no notifications and no keepalive */
if(notifications == 0) {
@@ -53818,51 +58959,60 @@ UA_Subscription_publish(UA_Server *server, UA_Subscription *sub) {
UA_Session_queuePublishReq(sub->session, pre, true); /* Re-enqueue */
return;
}
- UA_LOG_DEBUG_SESSION(&server->config.logger, sub->session,
- "Subscription %" PRIu32 " | Sending a KeepAlive",
- sub->subscriptionId);
+ UA_LOG_DEBUG_SUBSCRIPTION(&server->config.logger, sub, "Sending a KeepAlive");
}
- /* We want to send a response. Is the channel open? */
- UA_SecureChannel *channel = sub->session->header.channel;
- if(!channel || !pre) {
- UA_LOG_DEBUG_SESSION(&server->config.logger, sub->session,
- "Subscription %" PRIu32 " | Want to send a publish response but can't. "
- "The subscription is late.", sub->subscriptionId);
- sub->state = UA_SUBSCRIPTIONSTATE_LATE;
+ /* We want to send a response, but cannot. Either because there is no queued
+ * response or because the Subscription is detached from a Session or because
+ * the SecureChannel for the Session is closed. */
+ if(!pre || !sub->session || !sub->session->header.channel) {
+ UA_LOG_DEBUG_SUBSCRIPTION(&server->config.logger, sub,
+ "Want to send a publish response but cannot. "
+ "The subscription is late.");
+ UA_Subscription_isLate(sub);
if(pre)
UA_Session_queuePublishReq(sub->session, pre, true); /* Re-enqueue */
return;
}
+ UA_assert(pre);
+ UA_assert(sub->session); /* Otherwise pre is NULL */
+
/* Prepare the response */
UA_PublishResponse *response = &pre->response;
UA_NotificationMessage *message = &response->notificationMessage;
UA_NotificationMessageEntry *retransmission = NULL;
+#ifdef UA_ENABLE_DIAGNOSTICS
+ size_t priorDataChangeNotifications = sub->dataChangeNotifications;
+ size_t priorEventNotifications = sub->eventNotifications;
+#endif
if(notifications > 0) {
if(server->config.enableRetransmissionQueue) {
/* Allocate the retransmission entry */
- retransmission = (UA_NotificationMessageEntry*)UA_malloc(sizeof(UA_NotificationMessageEntry));
+ retransmission = (UA_NotificationMessageEntry*)
+ UA_malloc(sizeof(UA_NotificationMessageEntry));
if(!retransmission) {
- UA_LOG_WARNING_SESSION(&server->config.logger, sub->session,
- "Subscription %" PRIu32 " | Could not allocate memory for retransmission. "
- "The subscription is late.", sub->subscriptionId);
- sub->state = UA_SUBSCRIPTIONSTATE_LATE;
+ UA_LOG_WARNING_SUBSCRIPTION(&server->config.logger, sub,
+ "Could not allocate memory for retransmission. "
+ "The subscription is late.");
+
+ UA_Subscription_isLate(sub);
UA_Session_queuePublishReq(sub->session, pre, true); /* Re-enqueue */
return;
}
}
/* Prepare the response */
- UA_StatusCode retval = prepareNotificationMessage(server, sub, message, notifications);
+ UA_StatusCode retval =
+ prepareNotificationMessage(server, sub, message, notifications);
if(retval != UA_STATUSCODE_GOOD) {
- UA_LOG_WARNING_SESSION(&server->config.logger, sub->session,
- "Subscription %" PRIu32 " | Could not prepare the notification message. "
- "The subscription is late.", sub->subscriptionId);
+ UA_LOG_WARNING_SUBSCRIPTION(&server->config.logger, sub,
+ "Could not prepare the notification message. "
+ "The subscription is late.");
/* If the retransmission queue is enabled a retransmission message is allocated */
if(retransmission)
UA_free(retransmission);
- sub->state = UA_SUBSCRIPTIONSTATE_LATE;
+ UA_Subscription_isLate(sub);
UA_Session_queuePublishReq(sub->session, pre, true); /* Re-enqueue */
return;
}
@@ -53870,9 +59020,8 @@ UA_Subscription_publish(UA_Server *server, UA_Subscription *sub) {
/* <-- The point of no return --> */
- /* Adjust the number of ready notifications */
- UA_assert(sub->readyNotifications >= notifications);
- sub->readyNotifications -= notifications;
+ /* Notifications remaining? */
+ UA_Boolean moreNotifications = (sub->notificationQueueSize > 0);
/* Set up the response */
response->responseHeader.timestamp = UA_DateTime_now();
@@ -53880,44 +59029,44 @@ UA_Subscription_publish(UA_Server *server, UA_Subscription *sub) {
response->moreNotifications = moreNotifications;
message->publishTime = response->responseHeader.timestamp;
- /* Set sequence number to message. Started at 1 which is given
- * during creating a new subscription. The 1 is required for
- * initial publish response with or without an monitored item. */
+ /* Set sequence number to message. Started at 1 which is given during
+ * creating a new subscription. The 1 is required for initial publish
+ * response with or without an monitored item. */
message->sequenceNumber = sub->nextSequenceNumber;
if(notifications > 0) {
- /* If the retransmission queue is enabled a retransmission message is allocated */
+ /* If the retransmission queue is enabled a retransmission message is
+ * allocated */
if(retransmission) {
/* Put the notification message into the retransmission queue. This
- * needs to be done here, so that the message itself is included in the
- * available sequence numbers for acknowledgement. */
+ * needs to be done here, so that the message itself is included in
+ * the available sequence numbers for acknowledgement. */
retransmission->message = response->notificationMessage;
UA_Subscription_addRetransmissionMessage(server, sub, retransmission);
}
- /* Only if a notification was created, the sequence number must be increased.
- * For a keepalive the sequence number can be reused. */
- sub->nextSequenceNumber = UA_Subscription_nextSequenceNumber(sub->nextSequenceNumber);
+ /* Only if a notification was created, the sequence number must be
+ * increased. For a keepalive the sequence number can be reused. */
+ sub->nextSequenceNumber =
+ UA_Subscription_nextSequenceNumber(sub->nextSequenceNumber);
}
/* Get the available sequence numbers from the retransmission queue */
- size_t available = sub->retransmissionQueueSize;
- UA_STACKARRAY(UA_UInt32, seqNumbers, available);
- if(available > 0) {
- response->availableSequenceNumbers = seqNumbers;
- response->availableSequenceNumbersSize = available;
- size_t i = 0;
- UA_NotificationMessageEntry *nme;
- TAILQ_FOREACH(nme, &sub->retransmissionQueue, listEntry) {
- response->availableSequenceNumbers[i] = nme->message.sequenceNumber;
- ++i;
- }
+ UA_assert(sub->retransmissionQueueSize <= UA_MAX_RETRANSMISSIONQUEUESIZE);
+ UA_UInt32 seqNumbers[UA_MAX_RETRANSMISSIONQUEUESIZE];
+ response->availableSequenceNumbers = seqNumbers;
+ response->availableSequenceNumbersSize = sub->retransmissionQueueSize;
+ size_t i = 0;
+ UA_NotificationMessageEntry *nme;
+ TAILQ_FOREACH(nme, &sub->retransmissionQueue, listEntry) {
+ response->availableSequenceNumbers[i] = nme->message.sequenceNumber;
+ ++i;
}
+ UA_assert(i == sub->retransmissionQueueSize);
/* Send the response */
- UA_LOG_DEBUG_SESSION(&server->config.logger, sub->session,
- "Subscription %" PRIu32 " | Sending out a publish response "
- "with %" PRIu32 " notifications", sub->subscriptionId,
- notifications);
+ UA_LOG_DEBUG_SUBSCRIPTION(&server->config.logger, sub,
+ "Sending out a publish response with %" PRIu32
+ " notifications", notifications);
sendResponse(server, sub->session, sub->session->header.channel, pre->requestId,
(UA_Response*)response, &UA_TYPES[UA_TYPES_PUBLISHRESPONSE]);
@@ -53934,13 +59083,25 @@ UA_Subscription_publish(UA_Server *server, UA_Subscription *sub) {
UA_PublishResponse_clear(&pre->response);
UA_free(pre);
+ /* Update the diagnostics statistics */
+#ifdef UA_ENABLE_DIAGNOSTICS
+ sub->publishRequestCount++;
+
+ UA_UInt32 sentDCN = (UA_UInt32)
+ (priorDataChangeNotifications - sub->dataChangeNotifications);
+ UA_UInt32 sentEN = (UA_UInt32)(priorEventNotifications - sub->eventNotifications);
+ sub->dataChangeNotificationsCount += sentDCN;
+ sub->eventNotificationsCount += sentEN;
+ sub->notificationsCount += (sentDCN + sentEN);
+#endif
+
/* Repeat sending responses if there are more notifications to send */
if(moreNotifications)
UA_Subscription_publish(server, sub);
}
UA_Boolean
-UA_Subscription_reachedPublishReqLimit(UA_Server *server, UA_Session *session) {
+UA_Session_reachedPublishReqLimit(UA_Server *server, UA_Session *session) {
UA_LOG_DEBUG_SESSION(&server->config.logger, session,
"Reached number of publish request limit");
@@ -53949,7 +59110,8 @@ UA_Subscription_reachedPublishReqLimit(UA_Server *server, UA_Session *session)
/* Cannot publish without a response */
if(!pre) {
- UA_LOG_FATAL_SESSION(&server->config.logger, session, "No publish requests available");
+ UA_LOG_FATAL_SESSION(&server->config.logger, session,
+ "No publish requests available");
return false;
}
@@ -53982,60 +59144,38 @@ UA_Subscription_reachedPublishReqLimit(UA_Server *server, UA_Session *session)
UA_StatusCode
Subscription_registerPublishCallback(UA_Server *server, UA_Subscription *sub) {
- UA_LOG_DEBUG_SESSION(&server->config.logger, sub->session,
- "Subscription %" PRIu32 " | Register subscription "
- "publishing callback", sub->subscriptionId);
- UA_LOCK_ASSERT(server->serviceMutex, 1);
+ UA_LOG_DEBUG_SUBSCRIPTION(&server->config.logger, sub,
+ "Register subscription publishing callback");
+ UA_LOCK_ASSERT(&server->serviceMutex, 1);
- if(sub->publishCallbackIsRegistered)
+ if(sub->publishCallbackId > 0)
return UA_STATUSCODE_GOOD;
UA_StatusCode retval =
addRepeatedCallback(server, (UA_ServerCallback)publishCallback,
- sub, (UA_UInt32)sub->publishingInterval, &sub->publishCallbackId);
+ sub, sub->publishingInterval, &sub->publishCallbackId);
if(retval != UA_STATUSCODE_GOOD)
return retval;
- sub->publishCallbackIsRegistered = true;
+ UA_assert(sub->publishCallbackId > 0);
return UA_STATUSCODE_GOOD;
}
void
Subscription_unregisterPublishCallback(UA_Server *server, UA_Subscription *sub) {
- UA_LOG_DEBUG_SESSION(&server->config.logger, sub->session, "Subscription %" PRIu32 " | "
- "Unregister subscription publishing callback", sub->subscriptionId);
+ UA_LOG_DEBUG_SUBSCRIPTION(&server->config.logger, sub,
+ "Unregister subscription publishing callback");
- if(!sub->publishCallbackIsRegistered)
+ if(sub->publishCallbackId == 0)
return;
removeCallback(server, sub->publishCallbackId);
- sub->publishCallbackIsRegistered = false;
-}
-
-/* When the session has publish requests stored but the last subscription is
- * deleted... Send out empty responses */
-void
-UA_Subscription_answerPublishRequestsNoSubscription(UA_Server *server, UA_Session *session) {
- /* No session or there are remaining subscriptions */
- if(!session || LIST_FIRST(&session->serverSubscriptions))
- return;
-
- /* Send a response for every queued request */
- UA_PublishResponseEntry *pre;
- while((pre = UA_Session_dequeuePublishReq(session))) {
- UA_PublishResponse *response = &pre->response;
- response->responseHeader.serviceResult = UA_STATUSCODE_BADNOSUBSCRIPTION;
- response->responseHeader.timestamp = UA_DateTime_now();
- sendResponse(server, session, session->header.channel, pre->requestId,
- (UA_Response*)response, &UA_TYPES[UA_TYPES_PUBLISHRESPONSE]);
- UA_PublishResponse_clear(response);
- UA_free(pre);
- }
+ sub->publishCallbackId = 0;
}
#endif /* UA_ENABLE_SUBSCRIPTIONS */
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/src/server/ua_subscription_monitoreditem.c" ***********************************/
+/**** amalgamated original file "/src/server/ua_subscription_monitoreditem.c" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -54046,6 +59186,7 @@ UA_Subscription_answerPublishRequestsNoSubscription(UA_Server *server, UA_Sessio
* Copyright 2018 (c) Ari Breitkreuz, fortiss GmbH
* Copyright 2018 (c) Thomas Stalder, Blue Time Concept SA
* Copyright 2018 (c) Fabian Arndt, Root-Core
+ * Copyright 2020-2021 (c) Christian von Arnim, ISW University of Stuttgart (for VDW and umati)
*/
@@ -54057,175 +59198,357 @@ UA_Subscription_answerPublishRequestsNoSubscription(UA_Server *server, UA_Sessio
#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
-static const UA_NodeId overflowEventType =
+static const UA_NodeId eventQueueOverflowEventType =
{0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_EVENTQUEUEOVERFLOWEVENTTYPE}};
-static const UA_NodeId simpleOverflowEventType =
- {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_SIMPLEOVERFLOWEVENTTYPE}};
-
-static UA_Boolean
-UA_Notification_isOverflowEvent(UA_Server *server, UA_Notification *n) {
- UA_MonitoredItem *mon = n->mon;
- if(mon->attributeId != UA_ATTRIBUTEID_EVENTNOTIFIER)
- return false;
-
- UA_EventFieldList *efl = &n->data.event.fields;
- if(efl->eventFieldsSize >= 1 &&
- efl->eventFields[0].type == &UA_TYPES[UA_TYPES_NODEID] &&
- isNodeInTree(server, (const UA_NodeId *)efl->eventFields[0].data,
- &overflowEventType, &subtypeId, 1)) {
- return true;
- }
-
- return false;
-}
/* The specification states in Part 4 5.12.1.5 that an EventQueueOverflowEvent
* "is generated when the first Event has to be discarded [...] without
* discarding any other event". So only generate one for all deleted events. */
static UA_StatusCode
createEventOverflowNotification(UA_Server *server, UA_Subscription *sub,
- UA_MonitoredItem *mon, UA_Notification *indicator) {
- /* Avoid two redundant overflow events in a row */
- if((mon->discardOldest && UA_Notification_isOverflowEvent(server, indicator))
- || (!mon->discardOldest && TAILQ_PREV(indicator, NotificationQueue, listEntry) != NULL &&
- UA_Notification_isOverflowEvent(server, TAILQ_PREV(indicator, NotificationQueue, listEntry))))
- return UA_STATUSCODE_GOOD;
+ UA_MonitoredItem *mon) {
+ /* Avoid creating two adjacent overflow events */
+ UA_Notification *indicator = NULL;
+ if(mon->parameters.discardOldest) {
+ indicator = TAILQ_FIRST(&mon->queue);
+ UA_assert(indicator); /* must exist */
+ if(indicator->isOverflowEvent)
+ return UA_STATUSCODE_GOOD;
+ } else {
+ indicator = TAILQ_LAST(&mon->queue, NotificationQueue);
+ UA_assert(indicator); /* must exist */
+ /* Skip the last element. It is the recently added notification that
+ * shall be kept. We know it is not an OverflowEvent. */
+ UA_Notification *before = TAILQ_PREV(indicator, NotificationQueue, localEntry);
+ if(before && before->isOverflowEvent)
+ return UA_STATUSCODE_GOOD;
+ }
- /* A notification is inserted into the queue which includes only the
- * NodeId of the overflowEventType. It is up to the client to check for
- * possible overflows. */
+ /* A Notification is inserted into the queue which includes only the
+ * NodeId of the OverflowEventType. */
/* Allocate the notification */
- UA_Notification *overflowNotification = (UA_Notification *)
- UA_malloc(sizeof(UA_Notification));
+ UA_Notification *overflowNotification = UA_Notification_new();
if(!overflowNotification)
return UA_STATUSCODE_BADOUTOFMEMORY;
/* Set the notification fields */
+ overflowNotification->isOverflowEvent = true;
overflowNotification->mon = mon;
- UA_EventFieldList_init(&overflowNotification->data.event.fields);
- overflowNotification->data.event.fields.eventFields = UA_Variant_new();
- if(!overflowNotification->data.event.fields.eventFields) {
+ overflowNotification->data.event.clientHandle = mon->parameters.clientHandle;
+ overflowNotification->data.event.eventFields = UA_Variant_new();
+ if(!overflowNotification->data.event.eventFields) {
UA_free(overflowNotification);
return UA_STATUSCODE_BADOUTOFMEMORY;
}
- overflowNotification->data.event.fields.eventFieldsSize = 1;
+ overflowNotification->data.event.eventFieldsSize = 1;
UA_StatusCode retval =
- UA_Variant_setScalarCopy(overflowNotification->data.event.fields.eventFields,
- &simpleOverflowEventType, &UA_TYPES[UA_TYPES_NODEID]);
+ UA_Variant_setScalarCopy(overflowNotification->data.event.eventFields,
+ &eventQueueOverflowEventType, &UA_TYPES[UA_TYPES_NODEID]);
if(retval != UA_STATUSCODE_GOOD) {
- UA_EventFieldList_clear(&overflowNotification->data.event.fields);
- UA_free(overflowNotification);
+ UA_Notification_delete(overflowNotification);
return retval;
}
- /* Insert before the "indicator notification". This is either first in the
+ /* Insert before the removed notification. This is either first in the
* queue (if the oldest notification was removed) or before the new event
- * that remains the last element of the queue. */
- TAILQ_INSERT_BEFORE(indicator, overflowNotification, listEntry);
+ * that remains the last element of the queue.
+ *
+ * Ensure that the following is consistent with UA_Notification_enqueueMon
+ * and UA_Notification_enqueueSub! */
+ TAILQ_INSERT_BEFORE(indicator, overflowNotification, localEntry);
++mon->eventOverflows;
++mon->queueSize;
- TAILQ_NEXT(overflowNotification, globalEntry) = UA_SUBSCRIPTION_QUEUE_SENTINEL;
- if(mon->monitoringMode == UA_MONITORINGMODE_REPORTING) {
+ /* Test for consistency */
+ UA_assert(mon->queueSize >= mon->eventOverflows);
+ UA_assert(mon->eventOverflows <= mon->queueSize - mon->eventOverflows + 1);
+
+ if(TAILQ_NEXT(indicator, globalEntry) != UA_SUBSCRIPTION_QUEUE_SENTINEL) {
+ /* Insert just before the indicator */
TAILQ_INSERT_BEFORE(indicator, overflowNotification, globalEntry);
- ++sub->notificationQueueSize;
- ++sub->eventNotifications;
+ } else {
+ /* The indicator was not reporting or not added yet. */
+ if(!mon->parameters.discardOldest) {
+ /* Add last to the per-Subscription queue */
+ TAILQ_INSERT_TAIL(&mon->subscription->notificationQueue,
+ overflowNotification, globalEntry);
+ } else {
+ /* Find the oldest reported element. Add before that. */
+ while(indicator) {
+ indicator = TAILQ_PREV(indicator, NotificationQueue, localEntry);
+ if(!indicator) {
+ TAILQ_INSERT_TAIL(&mon->subscription->notificationQueue,
+ overflowNotification, globalEntry);
+ break;
+ }
+ if(TAILQ_NEXT(indicator, globalEntry) != UA_SUBSCRIPTION_QUEUE_SENTINEL) {
+ TAILQ_INSERT_BEFORE(indicator, overflowNotification, globalEntry);
+ break;
+ }
+ }
+ }
}
+
+ ++sub->notificationQueueSize;
+ ++sub->eventNotifications;
+
+ /* Update the diagnostics statistics */
+#ifdef UA_ENABLE_DIAGNOSTICS
+ sub->eventQueueOverFlowCount++;
+#endif
+
return UA_STATUSCODE_GOOD;
}
#endif
-/* !!! The enqueue and dequeue operations need to match the reporting
- * disable/enable logic in Operation_SetMonitoringMode !!! */
+/* Set the InfoBits that a datachange notification was removed */
+static void
+setOverflowInfoBits(UA_MonitoredItem *mon) {
+ /* Only for queues with more than one element */
+ if(mon->parameters.queueSize == 1)
+ return;
+
+ UA_Notification *indicator = NULL;
+ if(mon->parameters.discardOldest) {
+ indicator = TAILQ_FIRST(&mon->queue);
+ } else {
+ indicator = TAILQ_LAST(&mon->queue, NotificationQueue);
+ }
+ UA_assert(indicator); /* must exist */
+
+ indicator->data.dataChange.value.hasStatus = true;
+ indicator->data.dataChange.value.status |=
+ (UA_STATUSCODE_INFOTYPE_DATAVALUE | UA_STATUSCODE_INFOBITS_OVERFLOW);
+}
+/* Remove the InfoBits when the queueSize was reduced to 1 */
void
-UA_Notification_enqueue(UA_Server *server, UA_Subscription *sub,
- UA_MonitoredItem *mon, UA_Notification *n) {
+UA_MonitoredItem_removeOverflowInfoBits(UA_MonitoredItem *mon) {
+ /* Don't consider queue size > 1 and Event MonitoredItems */
+ if(mon->parameters.queueSize > 1 ||
+ mon->itemToMonitor.attributeId == UA_ATTRIBUTEID_EVENTNOTIFIER)
+ return;
+
+ /* Get the first notification */
+ UA_Notification *n = TAILQ_FIRST(&mon->queue);
+ if(!n)
+ return;
+
+ /* Assertion that at most one notification is in the queue */
+ UA_assert(n == TAILQ_LAST(&mon->queue, NotificationQueue));
+
+ /* Remve the Infobits */
+ n->data.dataChange.value.status &= ~(UA_StatusCode)
+ (UA_STATUSCODE_INFOTYPE_DATAVALUE | UA_STATUSCODE_INFOBITS_OVERFLOW);
+}
+
+UA_Notification *
+UA_Notification_new(void) {
+ UA_Notification *n = (UA_Notification*)UA_calloc(1, sizeof(UA_Notification));
+ if(n) {
+ /* Set the sentinel for a notification that is not enqueued */
+ TAILQ_NEXT(n, globalEntry) = UA_SUBSCRIPTION_QUEUE_SENTINEL;
+ TAILQ_NEXT(n, localEntry) = UA_SUBSCRIPTION_QUEUE_SENTINEL;
+ }
+ return n;
+}
+
+static void UA_Notification_dequeueMon(UA_Notification *n);
+static void UA_Notification_enqueueSub(UA_Notification *n);
+static void UA_Notification_dequeueSub(UA_Notification *n);
+
+void
+UA_Notification_delete(UA_Notification *n) {
+ UA_assert(n != UA_SUBSCRIPTION_QUEUE_SENTINEL);
+ if(n->mon) {
+ UA_Notification_dequeueMon(n);
+ UA_Notification_dequeueSub(n);
+ switch(n->mon->itemToMonitor.attributeId) {
+#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
+ case UA_ATTRIBUTEID_EVENTNOTIFIER:
+ UA_EventFieldList_clear(&n->data.event);
+ UA_EventFilterResult_clear(&n->result);
+ break;
+#endif
+ default:
+ UA_MonitoredItemNotification_clear(&n->data.dataChange);
+ break;
+ }
+ }
+ UA_free(n);
+}
+
+/* Add to the MonitoredItem queue, update all counters and then handle overflow */
+static void
+UA_Notification_enqueueMon(UA_Server *server, UA_Notification *n) {
+ UA_MonitoredItem *mon = n->mon;
+ UA_assert(mon);
+ UA_assert(TAILQ_NEXT(n, localEntry) == UA_SUBSCRIPTION_QUEUE_SENTINEL);
+
/* Add to the MonitoredItem */
- TAILQ_INSERT_TAIL(&mon->queue, n, listEntry);
+ TAILQ_INSERT_TAIL(&mon->queue, n, localEntry);
++mon->queueSize;
#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
- if(mon->attributeId == UA_ATTRIBUTEID_EVENTNOTIFIER &&
- UA_Notification_isOverflowEvent(server, n))
+ if(n->isOverflowEvent)
++mon->eventOverflows;
#endif
- /* Add to the subscription if reporting is enabled */
- TAILQ_NEXT(n, globalEntry) = UA_SUBSCRIPTION_QUEUE_SENTINEL;
- if(mon->monitoringMode == UA_MONITORINGMODE_REPORTING) {
- TAILQ_INSERT_TAIL(&sub->notificationQueue, n, globalEntry);
- ++sub->notificationQueueSize;
-#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
- if(mon->attributeId == UA_ATTRIBUTEID_EVENTNOTIFIER) {
- ++sub->eventNotifications;
- } else
-#endif
- {
- ++sub->dataChangeNotifications;
- }
- }
+ /* Test for consistency */
+ UA_assert(mon->queueSize >= mon->eventOverflows);
+ UA_assert(mon->eventOverflows <= mon->queueSize - mon->eventOverflows + 1);
/* Ensure enough space is available in the MonitoredItem. Do this only after
* adding the new Notification. */
UA_MonitoredItem_ensureQueueSpace(server, mon);
+
+ UA_LOG_DEBUG_SUBSCRIPTION(&server->config.logger, mon->subscription,
+ "MonitoredItem %" PRIi32 " | "
+ "Notification enqueued (Queue size %lu / %lu)",
+ mon->monitoredItemId,
+ (long unsigned)mon->queueSize,
+ (long unsigned)mon->parameters.queueSize);
}
void
-UA_Notification_dequeue(UA_Server *server, UA_Notification *n) {
+UA_Notification_enqueueSub(UA_Notification *n) {
UA_MonitoredItem *mon = n->mon;
+ UA_assert(mon);
+
UA_Subscription *sub = mon->subscription;
+ UA_assert(sub);
- /* Remove from the MonitoredItem queue */
-#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
- if(mon->attributeId == UA_ATTRIBUTEID_EVENTNOTIFIER &&
- UA_Notification_isOverflowEvent(server, n))
- --mon->eventOverflows;
-#endif
- TAILQ_REMOVE(&mon->queue, n, listEntry);
- --mon->queueSize;
+ if(TAILQ_NEXT(n, globalEntry) != UA_SUBSCRIPTION_QUEUE_SENTINEL)
+ return;
+
+ /* Add to the subscription if reporting is enabled */
+ TAILQ_INSERT_TAIL(&sub->notificationQueue, n, globalEntry);
+ ++sub->notificationQueueSize;
- /* Remove from the subscription's queue */
- if(TAILQ_NEXT(n, globalEntry) != UA_SUBSCRIPTION_QUEUE_SENTINEL) {
+ switch(mon->itemToMonitor.attributeId) {
#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
- if(mon->attributeId == UA_ATTRIBUTEID_EVENTNOTIFIER) {
- --sub->eventNotifications;
- } else
+ case UA_ATTRIBUTEID_EVENTNOTIFIER:
+ ++sub->eventNotifications;
+ break;
#endif
- {
- --sub->dataChangeNotifications;
+ default:
+ ++sub->dataChangeNotifications;
+ break;
+ }
+}
+
+void
+UA_Notification_enqueueAndTrigger(UA_Server *server, UA_Notification *n) {
+ UA_MonitoredItem *mon = n->mon;
+ UA_Subscription *sub = mon->subscription;
+ UA_assert(sub); /* This function is never called for local MonitoredItems */
+
+ /* If reporting or (sampled+triggered), enqueue into the Subscription first
+ * and then into the MonitoredItem. UA_MonitoredItem_ensureQueueSpace
+ * (called within UA_Notification_enqueueMon) assumes the notification is
+ * already in the Subscription's publishing queue. */
+ if(mon->monitoringMode == UA_MONITORINGMODE_REPORTING ||
+ (mon->monitoringMode == UA_MONITORINGMODE_SAMPLING &&
+ mon->triggeredUntil > UA_DateTime_nowMonotonic())) {
+ UA_Notification_enqueueSub(n);
+ mon->triggeredUntil = UA_INT64_MIN;
+ UA_LOG_DEBUG_SUBSCRIPTION(&server->config.logger, mon->subscription,
+ "Notification enqueued (Queue size %lu)",
+ (long unsigned)mon->subscription->notificationQueueSize);
+ }
+
+ /* Insert into the MonitoredItem. This checks the queue size and
+ * handles overflow. */
+ UA_Notification_enqueueMon(server, n);
+
+ for(size_t i = mon->triggeringLinksSize - 1; i < mon->triggeringLinksSize; i--) {
+ /* Get the triggered MonitoredItem. Remove the link if the MI doesn't exist. */
+ UA_MonitoredItem *triggeredMon =
+ UA_Subscription_getMonitoredItem(sub, mon->triggeringLinks[i]);
+ if(!triggeredMon) {
+ UA_MonitoredItem_removeLink(sub, mon, mon->triggeringLinks[i]);
+ continue;
}
- /*
- see open issue #2114:
- in the function UA_MonitoredItem_ensureQueueSpace, a greater overflow event size
- than event queue size will result in false assertion.
- to fix this problem, we assume that only one overflow event is allowed, so by
- dequeueing a notification, we remove the overflow event by setting its size to 0.
- */
- //mon->eventOverflows = 0;
+ /* Only sampling MonitoredItems receive a trigger. Reporting
+ * MonitoredItems send out Notifications anyway and disabled
+ * MonitoredItems don't create samples to send. */
+ if(triggeredMon->monitoringMode != UA_MONITORINGMODE_SAMPLING)
+ continue;
- TAILQ_REMOVE(&sub->notificationQueue, n, globalEntry);
- --sub->notificationQueueSize;
+ /* Get the latest sampled Notification from the triggered MonitoredItem.
+ * Enqueue for publication. */
+ UA_Notification *n2 = TAILQ_LAST(&triggeredMon->queue, NotificationQueue);
+ if(n2)
+ UA_Notification_enqueueSub(n2);
+
+ /* The next Notification within the publishing interval is going to be
+ * published as well. (Falsely) assume that the publishing cycle has
+ * started right now, so that we don't have to loop over MonitoredItems
+ * to deactivate the triggering after the publishing cycle. */
+ triggeredMon->triggeredUntil = UA_DateTime_nowMonotonic() +
+ (UA_DateTime)(sub->publishingInterval * (UA_Double)UA_DATETIME_MSEC);
+
+ UA_LOG_DEBUG_SUBSCRIPTION(&server->config.logger, sub,
+ "MonitoredItem %u triggers MonitoredItem %u",
+ mon->monitoredItemId, triggeredMon->monitoredItemId);
}
}
-void
-UA_Notification_delete(UA_Notification *n) {
+/* Remove from the MonitoredItem queue and adjust all counters */
+static void
+UA_Notification_dequeueMon(UA_Notification *n) {
+ UA_MonitoredItem *mon = n->mon;
+ UA_assert(mon);
+
+ if(TAILQ_NEXT(n, localEntry) == UA_SUBSCRIPTION_QUEUE_SENTINEL)
+ return;
+
+ /* Remove from the MonitoredItem queue */
#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
+ if(n->isOverflowEvent)
+ --mon->eventOverflows;
+#endif
+
+ TAILQ_REMOVE(&mon->queue, n, localEntry);
+ --mon->queueSize;
+
+ /* Test for consistency */
+ UA_assert(mon->queueSize >= mon->eventOverflows);
+ UA_assert(mon->eventOverflows <= mon->queueSize - mon->eventOverflows + 1);
+
+ /* Reset the sentintel */
+ TAILQ_NEXT(n, localEntry) = UA_SUBSCRIPTION_QUEUE_SENTINEL;
+}
+
+void
+UA_Notification_dequeueSub(UA_Notification *n) {
+ if(TAILQ_NEXT(n, globalEntry) == UA_SUBSCRIPTION_QUEUE_SENTINEL)
+ return;
+
UA_MonitoredItem *mon = n->mon;
- if(mon->attributeId == UA_ATTRIBUTEID_EVENTNOTIFIER) {
- UA_EventFieldList_clear(&n->data.event.fields);
- /* EventFilterResult currently isn't being used
- * UA_EventFilterResult_delete(notification->data.event->result); */
- } else
+ UA_assert(mon);
+ UA_Subscription *sub = mon->subscription;
+ UA_assert(sub);
+
+ switch(mon->itemToMonitor.attributeId) {
+#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
+ case UA_ATTRIBUTEID_EVENTNOTIFIER:
+ --sub->eventNotifications;
+ break;
#endif
- {
- UA_DataValue_clear(&n->data.value);
+ default:
+ --sub->dataChangeNotifications;
+ break;
}
- UA_free(n);
+
+ TAILQ_REMOVE(&sub->notificationQueue, n, globalEntry);
+ --sub->notificationQueueSize;
+
+ /* Reset the sentinel */
+ TAILQ_NEXT(n, globalEntry) = UA_SUBSCRIPTION_QUEUE_SENTINEL;
}
/*****************/
@@ -54233,204 +59556,458 @@ UA_Notification_delete(UA_Notification *n) {
/*****************/
void
-UA_MonitoredItem_init(UA_MonitoredItem *mon, UA_Subscription *sub) {
+UA_MonitoredItem_init(UA_MonitoredItem *mon) {
memset(mon, 0, sizeof(UA_MonitoredItem));
- mon->subscription = sub;
+ mon->next = (UA_MonitoredItem*)~0; /* Not added to a node */
TAILQ_INIT(&mon->queue);
+ mon->triggeredUntil = UA_INT64_MIN;
}
-void
-UA_MonitoredItem_delete(UA_Server *server, UA_MonitoredItem *monitoredItem) {
- UA_LOCK_ASSERT(server->serviceMutex, 1);
+static UA_StatusCode
+addMonitoredItemBackpointer(UA_Server *server, UA_Session *session,
+ UA_Node *node, void *data) {
+ UA_MonitoredItem *mon = (UA_MonitoredItem*)data;
+ UA_assert(mon != (UA_MonitoredItem*)~0);
+ mon->next = node->head.monitoredItems;
+ node->head.monitoredItems = mon;
+ return UA_STATUSCODE_GOOD;
+}
- /* Remove the sampling callback */
- UA_MonitoredItem_unregisterSampleCallback(server, monitoredItem);
-
- /* Remove the queued notifications if attached to a subscription (not a
- * local MonitoredItem) */
- if(monitoredItem->subscription) {
- UA_Notification *notification, *notification_tmp;
- TAILQ_FOREACH_SAFE(notification, &monitoredItem->queue,
- listEntry, notification_tmp) {
- /* Remove the item from the queues and free the memory */
- UA_Notification_dequeue(server, notification);
- UA_Notification_delete(notification);
+static UA_StatusCode
+removeMonitoredItemBackPointer(UA_Server *server, UA_Session *session,
+ UA_Node *node, void *data) {
+ if(!node->head.monitoredItems)
+ return UA_STATUSCODE_GOOD;
+
+ /* Edge case that it's the first element */
+ UA_MonitoredItem *remove = (UA_MonitoredItem*)data;
+ if(node->head.monitoredItems == remove) {
+ node->head.monitoredItems = remove->next;
+ remove->next = (UA_MonitoredItem*)~0;
+ return UA_STATUSCODE_GOOD;
+ }
+
+ UA_MonitoredItem *prev = node->head.monitoredItems;
+ UA_MonitoredItem *entry = prev->next;
+ for(; entry != NULL; prev = entry, entry = entry->next) {
+ if(entry == remove) {
+ prev->next = entry->next;
+ remove->next = (UA_MonitoredItem*)~0;
+ break;
}
}
-#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
- if(monitoredItem->attributeId == UA_ATTRIBUTEID_EVENTNOTIFIER) {
- /* Remove the monitored item from the node queue */
- UA_Server_editNode(server, NULL, &monitoredItem->monitoredNodeId,
- UA_MonitoredItem_removeNodeEventCallback, monitoredItem);
- UA_EventFilter_clear(&monitoredItem->filter.eventFilter);
- } else
-#endif
- {
- /* UA_DataChangeFilter does not hold dynamic content we need to free */
- /* UA_DataChangeFilter_clear(&monitoredItem->filter.dataChangeFilter); */
+ return UA_STATUSCODE_GOOD;
+}
+
+void
+UA_Server_registerMonitoredItem(UA_Server *server, UA_MonitoredItem *mon) {
+ if(mon->registered)
+ return;
+
+ /* Register in Subscription and Server */
+ UA_Subscription *sub = mon->subscription;
+ if(sub) {
+ mon->monitoredItemId = ++sub->lastMonitoredItemId;
+ mon->subscription = sub;
+ sub->monitoredItemsSize++;
+ LIST_INSERT_HEAD(&sub->monitoredItems, mon, listEntry);
+ } else {
+ mon->monitoredItemId = ++server->lastLocalMonitoredItemId;
+ LIST_INSERT_HEAD(&server->localMonitoredItems, mon, listEntry);
+ }
+ server->monitoredItemsSize++;
+
+ /* Register the MonitoredItem in userland */
+ if(server->config.monitoredItemRegisterCallback) {
+ UA_Session *session = &server->adminSession;
+ if(sub)
+ session = sub->session;
+
+ void *targetContext = NULL;
+ getNodeContext(server, mon->itemToMonitor.nodeId, &targetContext);
+ UA_UNLOCK(&server->serviceMutex);
+ server->config.monitoredItemRegisterCallback(server,
+ session ? &session->sessionId : NULL,
+ session ? session->sessionHandle : NULL,
+ &mon->itemToMonitor.nodeId,
+ targetContext,
+ mon->itemToMonitor.attributeId, false);
+ UA_LOCK(&server->serviceMutex);
}
+ mon->registered = true;
+}
+
+static void
+UA_Server_unregisterMonitoredItem(UA_Server *server, UA_MonitoredItem *mon) {
+ if(!mon->registered)
+ return;
+
+ UA_Subscription *sub = mon->subscription;
+ UA_LOG_INFO_SUBSCRIPTION(&server->config.logger, sub,
+ "MonitoredItem %" PRIi32 " | Deleting the MonitoredItem",
+ mon->monitoredItemId);
+
/* Deregister MonitoredItem in userland */
- if(server->config.monitoredItemRegisterCallback && monitoredItem->registered) {
- /* Get the session context. Local MonitoredItems don't have a subscription. */
- UA_Session *session = NULL;
- if(monitoredItem->subscription)
- session = monitoredItem->subscription->session;
- if(!session)
- session = &server->adminSession;
+ if(server->config.monitoredItemRegisterCallback) {
+ UA_Session *session = &server->adminSession;
+ if(sub)
+ session = sub->session;
- /* Get the node context */
void *targetContext = NULL;
- getNodeContext(server, monitoredItem->monitoredNodeId, &targetContext);
+ getNodeContext(server, mon->itemToMonitor.nodeId, &targetContext);
+ UA_UNLOCK(&server->serviceMutex);
+ server->config.monitoredItemRegisterCallback(server,
+ session ? &session->sessionId : NULL,
+ session ? session->sessionHandle : NULL,
+ &mon->itemToMonitor.nodeId,
+ targetContext,
+ mon->itemToMonitor.attributeId, true);
+ UA_LOCK(&server->serviceMutex);
+ }
+
+ /* Deregister in Subscription and server */
+ if(sub)
+ sub->monitoredItemsSize--;
+ LIST_REMOVE(mon, listEntry); /* Also for LocalMonitoredItems */
+ server->monitoredItemsSize--;
+
+ mon->registered = false;
+}
+
+UA_StatusCode
+UA_MonitoredItem_setMonitoringMode(UA_Server *server, UA_MonitoredItem *mon,
+ UA_MonitoringMode monitoringMode) {
+ /* Check if the MonitoringMode is valid or not */
+ if(monitoringMode > UA_MONITORINGMODE_REPORTING)
+ return UA_STATUSCODE_BADMONITORINGMODEINVALID;
+
+ /* Set the MonitoringMode, store the old mode */
+ UA_MonitoringMode oldMode = mon->monitoringMode;
+ mon->monitoringMode = monitoringMode;
- /* Deregister */
- UA_UNLOCK(server->serviceMutex);
- server->config.monitoredItemRegisterCallback(server, &session->sessionId,
- session->sessionHandle,
- &monitoredItem->monitoredNodeId,
- targetContext, monitoredItem->attributeId, true);
- UA_LOCK(server->serviceMutex);
+ UA_Notification *notification;
+ /* Reporting is disabled. This causes all Notifications to be dequeued and
+ * deleted. Also remove the last samples so that we immediately generate a
+ * Notification when re-activated. */
+ if(mon->monitoringMode == UA_MONITORINGMODE_DISABLED) {
+ UA_Notification *notification_tmp;
+ UA_MonitoredItem_unregisterSampling(server, mon);
+ TAILQ_FOREACH_SAFE(notification, &mon->queue, localEntry, notification_tmp) {
+ UA_Notification_delete(notification);
+ }
+ UA_DataValue_clear(&mon->lastValue);
+ return UA_STATUSCODE_GOOD;
}
- /* Remove the monitored item */
- if(monitoredItem->listEntry.le_prev != NULL)
- LIST_REMOVE(monitoredItem, listEntry);
- UA_String_clear(&monitoredItem->indexRange);
- UA_ByteString_clear(&monitoredItem->lastSampledValue);
- UA_Variant_clear(&monitoredItem->lastValue);
- UA_NodeId_clear(&monitoredItem->monitoredNodeId);
+ /* When reporting is enabled, put all notifications that were already
+ * sampled into the global queue of the subscription. When sampling is
+ * enabled, remove all notifications from the global queue. !!! This needs
+ * to be the same operation as in UA_Notification_enqueue !!! */
+ if(mon->monitoringMode == UA_MONITORINGMODE_REPORTING) {
+ /* Make all notifications reporting. Re-enqueue to ensure they have the
+ * right order if some notifications are already reported by a trigger
+ * link. */
+ TAILQ_FOREACH(notification, &mon->queue, localEntry) {
+ UA_Notification_dequeueSub(notification);
+ UA_Notification_enqueueSub(notification);
+ }
+ } else /* mon->monitoringMode == UA_MONITORINGMODE_SAMPLING */ {
+ /* Make all notifications non-reporting */
+ TAILQ_FOREACH(notification, &mon->queue, localEntry)
+ UA_Notification_dequeueSub(notification);
+ }
+
+ /* Register the sampling callback with an interval. If registering the
+ * sampling callback failed, set to disabled. But don't delete the current
+ * notifications. */
+ UA_StatusCode res = UA_MonitoredItem_registerSampling(server, mon);
+ if(res != UA_STATUSCODE_GOOD) {
+ mon->monitoringMode = UA_MONITORINGMODE_DISABLED;
+ return res;
+ }
- /* No actual callback, just remove the structure */
- monitoredItem->delayedFreePointers.callback = NULL;
- UA_WorkQueue_enqueueDelayed(&server->workQueue, &monitoredItem->delayedFreePointers);
+ /* Manually create the first sample if the MonitoredItem was disabled, the
+ * MonitoredItem is now sampling (or reporting) and it is not an
+ * Event-MonitoredItem */
+ if(oldMode == UA_MONITORINGMODE_DISABLED &&
+ mon->monitoringMode > UA_MONITORINGMODE_DISABLED &&
+ mon->itemToMonitor.attributeId != UA_ATTRIBUTEID_EVENTNOTIFIER)
+ monitoredItem_sampleCallback(server, mon);
+
+ return UA_STATUSCODE_GOOD;
}
-UA_StatusCode
+void
+UA_MonitoredItem_delete(UA_Server *server, UA_MonitoredItem *mon) {
+ UA_LOCK_ASSERT(&server->serviceMutex, 1);
+
+ /* Remove the sampling callback */
+ UA_MonitoredItem_unregisterSampling(server, mon);
+
+ UA_assert(mon->next == (UA_MonitoredItem*)~0); /* Not attached to any node */
+
+ /* Deregister in Server and Subscription */
+ if(mon->registered)
+ UA_Server_unregisterMonitoredItem(server, mon);
+
+ /* Remove the TriggeringLinks */
+ if(mon->triggeringLinksSize > 0) {
+ UA_free(mon->triggeringLinks);
+ mon->triggeringLinks = NULL;
+ mon->triggeringLinksSize = 0;
+ }
+
+ /* Remove the queued notifications attached to the subscription */
+ UA_Notification *notification, *notification_tmp;
+ TAILQ_FOREACH_SAFE(notification, &mon->queue, localEntry, notification_tmp) {
+ UA_Notification_delete(notification);
+ }
+
+ /* Remove the settings */
+ UA_ReadValueId_clear(&mon->itemToMonitor);
+ UA_MonitoringParameters_clear(&mon->parameters);
+
+ /* Remove the last samples */
+ UA_DataValue_clear(&mon->lastValue);
+
+ /* Add a delayed callback to remove the MonitoredItem when the current jobs
+ * have completed. This is needed to allow that a local MonitoredItem can
+ * remove itself in the callback. */
+ mon->delayedFreePointers.callback = NULL;
+ mon->delayedFreePointers.application = server;
+ mon->delayedFreePointers.data = NULL;
+ mon->delayedFreePointers.nextTime = UA_DateTime_nowMonotonic() + 1;
+ mon->delayedFreePointers.interval = 0;
+ UA_Timer_addTimerEntry(&server->timer, &mon->delayedFreePointers, NULL);
+}
+
+void
UA_MonitoredItem_ensureQueueSpace(UA_Server *server, UA_MonitoredItem *mon) {
- /* Assert: The eventoverflow are counted in the queue size; There can be
- * only one eventoverflow more than normal entries */
+ /* There can be only one EventOverflow more than normal entries. Because
+ * EventOverflows are never adjacent. */
UA_assert(mon->queueSize >= mon->eventOverflows);
UA_assert(mon->eventOverflows <= mon->queueSize - mon->eventOverflows + 1);
- /* Nothing to do */
- if(mon->queueSize - mon->eventOverflows <= mon->maxQueueSize)
- return UA_STATUSCODE_GOOD;
+ /* Always attached to a Subscription (no local MonitoredItem) */
+ UA_Subscription *sub = mon->subscription;
+ UA_assert(sub);
-#ifdef __clang_analyzer__
- return UA_STATUSCODE_GOOD;
-#endif
+ /* Nothing to do */
+ if(mon->queueSize - mon->eventOverflows <= mon->parameters.queueSize)
+ return;
- /* Remove notifications until the queue size is reached */
- UA_Subscription *sub = mon->subscription;
- while(mon->queueSize - mon->eventOverflows > mon->maxQueueSize) {
- /* At least two notifications that are not eventOverflows in the queue */
+ /* Remove notifications until the required queue size is reached */
+ UA_Boolean reporting = false;
+ size_t remove = mon->queueSize - mon->eventOverflows - mon->parameters.queueSize;
+ while(remove > 0) {
+ /* The minimum queue size (without EventOverflows) is 1. At least two
+ * notifications that are not EventOverflows are in the queue. */
UA_assert(mon->queueSize - mon->eventOverflows >= 2);
/* Select the next notification to delete. Skip over overflow events. */
UA_Notification *del = NULL;
- if(mon->discardOldest) {
+ if(mon->parameters.discardOldest) {
/* Remove the oldest */
del = TAILQ_FIRST(&mon->queue);
-#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
- while(UA_Notification_isOverflowEvent(server, del))
- del = TAILQ_NEXT(del, listEntry); /* skip overflow events */
+#if defined(UA_ENABLE_SUBSCRIPTIONS_EVENTS) && !defined(__clang_analyzer__)
+ while(del->isOverflowEvent)
+ del = TAILQ_NEXT(del, localEntry); /* skip overflow events */
#endif
} else {
/* Remove the second newest (to keep the up-to-date notification).
* The last entry is not an OverflowEvent -- we just added it. */
del = TAILQ_LAST(&mon->queue, NotificationQueue);
- del = TAILQ_PREV(del, NotificationQueue, listEntry);
-#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
- while(UA_Notification_isOverflowEvent(server, del))
- del = TAILQ_PREV(del, NotificationQueue, listEntry); /* skip overflow events */
+ del = TAILQ_PREV(del, NotificationQueue, localEntry);
+#if defined(UA_ENABLE_SUBSCRIPTIONS_EVENTS) && !defined(__clang_analyzer__)
+ while(del->isOverflowEvent)
+ del = TAILQ_PREV(del, NotificationQueue, localEntry); /* skip overflow events */
#endif
}
UA_assert(del); /* There must have been one entry that can be deleted */
- /* If reporting is activated (entries are also in the subscriptions
- * global queue): Move the entry after del in the per-MonitoredItem
- * queue right after del in the global queue. (It is already right after
- * del in the per-MonitoredItem queue.) This is required so we don't
- * starve MonitoredItems with a high sampling interval by always
- * removing their first appearance in the gloal queue for the
- * Subscription. */
+ /* Only create OverflowEvents (and set InfoBits) if the notification
+ * that is removed is reported */
+ if(TAILQ_NEXT(del, globalEntry) != UA_SUBSCRIPTION_QUEUE_SENTINEL)
+ reporting = true;
+
+ /* Move the entry after del in the per-MonitoredItem queue right after
+ * del in the per-Subscription queue. So we don't starve MonitoredItems
+ * with a high sampling interval in the Subscription queue by always
+ * removing their first appearance in the per-Subscription queue.
+ *
+ * With MonitoringMode == SAMPLING, the Notifications are not (all) in
+ * the per-Subscription queue. Don't reinsert in that case.
+ *
+ * For the reinsertion to work, first insert into the per-Subscription
+ * queue. */
if(TAILQ_NEXT(del, globalEntry) != UA_SUBSCRIPTION_QUEUE_SENTINEL) {
- UA_Notification *after_del = TAILQ_NEXT(del, listEntry);
+ UA_Notification *after_del = TAILQ_NEXT(del, localEntry);
UA_assert(after_del); /* There must be one remaining element after del */
- TAILQ_REMOVE(&sub->notificationQueue, after_del, globalEntry);
- TAILQ_INSERT_AFTER(&sub->notificationQueue, del, after_del, globalEntry);
+ if(TAILQ_NEXT(after_del, globalEntry) != UA_SUBSCRIPTION_QUEUE_SENTINEL) {
+ TAILQ_REMOVE(&sub->notificationQueue, after_del, globalEntry);
+ TAILQ_INSERT_AFTER(&sub->notificationQueue, del, after_del, globalEntry);
+ }
}
- /* Delete the notification */
- UA_Notification_dequeue(server, del);
+ remove--;
+
+ /* Delete the notification and remove it from the queues */
UA_Notification_delete(del);
- }
- /* Get the element where the overflow shall be announced (infobits or
- * overflowevent) */
- UA_Notification *indicator;
- if(mon->discardOldest)
- indicator = TAILQ_FIRST(&mon->queue);
- else
- indicator = TAILQ_LAST(&mon->queue, NotificationQueue);
- UA_assert(indicator);
+ /* Update the subscription diagnostics statistics */
+#ifdef UA_ENABLE_DIAGNOSTICS
+ sub->monitoringQueueOverflowCount++;
+#endif
+
+ /* Assertions to help Clang's scan-analyzer */
+ UA_assert(del != TAILQ_FIRST(&mon->queue));
+ UA_assert(del != TAILQ_LAST(&mon->queue, NotificationQueue));
+ UA_assert(del != TAILQ_PREV(TAILQ_LAST(&mon->queue, NotificationQueue),
+ NotificationQueue, localEntry));
+ }
- /* Create an overflow notification */
+ /* Leave an entry to indicate that notifications were removed */
+ if(reporting) {
#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
- if(mon->attributeId == UA_ATTRIBUTEID_EVENTNOTIFIER) {
- return createEventOverflowNotification(server, sub, mon, indicator);
- } else
+ if(mon->itemToMonitor.attributeId == UA_ATTRIBUTEID_EVENTNOTIFIER)
+ createEventOverflowNotification(server, sub, mon);
+ else
#endif
- {
- /* Set the infobits of a datachange notification */
- if(mon->maxQueueSize > 1) {
- /* Add the infobits either to the newest or the new last entry */
- indicator->data.value.hasStatus = true;
- indicator->data.value.status |=
- (UA_STATUSCODE_INFOTYPE_DATAVALUE | UA_STATUSCODE_INFOBITS_OVERFLOW);
- }
+ setOverflowInfoBits(mon);
}
- return UA_STATUSCODE_GOOD;
}
UA_StatusCode
-UA_MonitoredItem_registerSampleCallback(UA_Server *server, UA_MonitoredItem *mon) {
- UA_LOCK_ASSERT(server->serviceMutex, 1);
+UA_MonitoredItem_registerSampling(UA_Server *server, UA_MonitoredItem *mon) {
+ UA_LOCK_ASSERT(&server->serviceMutex, 1);
if(mon->sampleCallbackIsRegistered)
return UA_STATUSCODE_GOOD;
- /* Only DataChange MonitoredItems have a callback with a sampling interval */
- if(mon->attributeId == UA_ATTRIBUTEID_EVENTNOTIFIER)
- return UA_STATUSCODE_GOOD;
+ UA_assert(mon->next == (UA_MonitoredItem*)~0); /* Not registered in a node */
+
+ /* Only DataChange MonitoredItems with a positive sampling interval have a
+ * repeated callback. Other MonitoredItems are attached to the Node in a
+ * linked list of backpointers. */
+ UA_StatusCode res;
+ if(mon->itemToMonitor.attributeId == UA_ATTRIBUTEID_EVENTNOTIFIER ||
+ mon->parameters.samplingInterval == 0.0) {
+ UA_Subscription *sub = mon->subscription;
+ UA_Session *session = &server->adminSession;
+ if(sub)
+ session = sub->session;
+ res = UA_Server_editNode(server, session, &mon->itemToMonitor.nodeId,
+ addMonitoredItemBackpointer, mon);
+ } else {
+ res = addRepeatedCallback(server,
+ (UA_ServerCallback)UA_MonitoredItem_sampleCallback,
+ mon, mon->parameters.samplingInterval,
+ &mon->sampleCallbackId);
+ }
- UA_StatusCode retval =
- addRepeatedCallback(server, (UA_ServerCallback)UA_MonitoredItem_sampleCallback,
- mon, mon->samplingInterval, &mon->sampleCallbackId);
- if(retval == UA_STATUSCODE_GOOD)
+ if(res == UA_STATUSCODE_GOOD)
mon->sampleCallbackIsRegistered = true;
- return retval;
+ return res;
}
void
-UA_MonitoredItem_unregisterSampleCallback(UA_Server *server, UA_MonitoredItem *mon) {
- UA_LOCK_ASSERT(server->serviceMutex, 1);
+UA_MonitoredItem_unregisterSampling(UA_Server *server, UA_MonitoredItem *mon) {
+ UA_LOCK_ASSERT(&server->serviceMutex, 1);
if(!mon->sampleCallbackIsRegistered)
return;
- removeCallback(server, mon->sampleCallbackId);
+
mon->sampleCallbackIsRegistered = false;
+
+ /* Check for mon->next and not the samplingInterval. Because that might
+ * currently be changed. */
+ if(mon->next != (UA_MonitoredItem*)~0) {
+ /* Added to a node */
+ UA_Subscription *sub = mon->subscription;
+ UA_Session *session = &server->adminSession;
+ if(sub)
+ session = sub->session;
+ UA_Server_editNode(server, session, &mon->itemToMonitor.nodeId,
+ removeMonitoredItemBackPointer, mon);
+ } else {
+ /* Registered with a repeated callback */
+ removeCallback(server, mon->sampleCallbackId);
+ }
+}
+
+UA_StatusCode
+UA_MonitoredItem_removeLink(UA_Subscription *sub, UA_MonitoredItem *mon, UA_UInt32 linkId) {
+ /* Find the index */
+ size_t i = 0;
+ for(; i < mon->triggeringLinksSize; i++) {
+ if(mon->triggeringLinks[i] == linkId)
+ break;
+ }
+
+ /* Not existing / already removed */
+ if(i == mon->triggeringLinksSize)
+ return UA_STATUSCODE_BADMONITOREDITEMIDINVALID;
+
+ /* Remove the link */
+ mon->triggeringLinksSize--;
+ if(mon->triggeringLinksSize == 0) {
+ UA_free(mon->triggeringLinks);
+ mon->triggeringLinks = NULL;
+ } else {
+ mon->triggeringLinks[i] = mon->triggeringLinks[mon->triggeringLinksSize];
+ UA_UInt32 *tmpLinks = (UA_UInt32*)
+ UA_realloc(mon->triggeringLinks, mon->triggeringLinksSize * sizeof(UA_UInt32));
+ if(tmpLinks)
+ mon->triggeringLinks = tmpLinks;
+ }
+
+ /* Does the target MonitoredItem exist? This is stupid, but the CTT wants us
+ * to to this. We don't auto-remove links together with the target
+ * MonitoredItem. Links to removed MonitoredItems are removed when the link
+ * triggers and the target no longer exists. */
+ UA_MonitoredItem *mon2 = UA_Subscription_getMonitoredItem(sub, linkId);
+ if(!mon2)
+ return UA_STATUSCODE_BADMONITOREDITEMIDINVALID;
+
+ return UA_STATUSCODE_GOOD;
+}
+
+UA_StatusCode
+UA_MonitoredItem_addLink(UA_Subscription *sub, UA_MonitoredItem *mon, UA_UInt32 linkId) {
+ /* Does the target MonitoredItem exist? */
+ UA_MonitoredItem *mon2 = UA_Subscription_getMonitoredItem(sub, linkId);
+ if(!mon2)
+ return UA_STATUSCODE_BADMONITOREDITEMIDINVALID;
+
+ /* Does the link already exist? */
+ for(size_t i = 0 ; i < mon->triggeringLinksSize; i++) {
+ if(mon->triggeringLinks[i] == linkId)
+ return UA_STATUSCODE_GOOD;
+ }
+
+ /* Allocate the memory */
+ UA_UInt32 *tmpLinkIds = (UA_UInt32*)
+ UA_realloc(mon->triggeringLinks, (mon->triggeringLinksSize + 1) * sizeof(UA_UInt32));
+ if(!tmpLinkIds)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ mon->triggeringLinks = tmpLinkIds;
+
+ /* Add the link */
+ mon->triggeringLinks[mon->triggeringLinksSize] = linkId;
+ mon->triggeringLinksSize++;
+ return UA_STATUSCODE_GOOD;
}
#endif /* UA_ENABLE_SUBSCRIPTIONS */
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/src/server/ua_subscription_datachange.c" ***********************************/
+/**** amalgamated original file "/src/server/ua_subscription_datachange.c" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
- * Copyright 2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
+ * Copyright 2017-2020 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
* Copyright 2017 (c) Stefan Profanter, fortiss GmbH
* Copyright 2018 (c) Ari Breitkreuz, fortiss GmbH
* Copyright 2018 (c) Thomas Stalder, Blue Time Concept SA
@@ -54440,240 +60017,170 @@ UA_MonitoredItem_unregisterSampleCallback(UA_Server *server, UA_MonitoredItem *m
#ifdef UA_ENABLE_SUBSCRIPTIONS /* conditional compilation */
-#define UA_VALUENCODING_MAXSTACK 512
+/* Detect value changes outside the deadband */
+#define UA_DETECT_DEADBAND(TYPE) do { \
+ TYPE v1 = *(const TYPE*)data1; \
+ TYPE v2 = *(const TYPE*)data2; \
+ TYPE diff = (v1 > v2) ? (TYPE)(v1 - v2) : (TYPE)(v2 - v1); \
+ return ((UA_Double)diff > deadband); \
+} while(false);
-/* Convert to double first. We might loose differences for large Int64 that
- * cannot be precisely expressed as double. */
static UA_Boolean
-outOfDeadBand(const void *data1, const void *data2,
- const UA_DataType *type, const UA_Double deadband) {
- UA_Double v;
- if(type == &UA_TYPES[UA_TYPES_BOOLEAN]) {
- v = (UA_Double)*(const UA_Boolean*)data1 - (UA_Double)*(const UA_Boolean*)data2;
- } else if(type == &UA_TYPES[UA_TYPES_SBYTE]) {
- v = (UA_Double)*(const UA_SByte*)data1 - (UA_Double)*(const UA_SByte*)data2;
- } else if(type == &UA_TYPES[UA_TYPES_BYTE]) {
- v = (UA_Double)*(const UA_Byte*)data1 - (UA_Double)*(const UA_Byte*)data2;
- } else if(type == &UA_TYPES[UA_TYPES_INT16]) {
- v = (UA_Double)*(const UA_Int16*)data1 - (UA_Double)*(const UA_Int16*)data2;
- } else if(type == &UA_TYPES[UA_TYPES_UINT16]) {
- v = (UA_Double)*(const UA_UInt16*)data1 - (UA_Double)*(const UA_UInt16*)data2;
- } else if(type == &UA_TYPES[UA_TYPES_INT32]) {
- v = (UA_Double)*(const UA_Int32*)data1 - (UA_Double)*(const UA_Int32*)data2;
- } else if(type == &UA_TYPES[UA_TYPES_UINT32]) {
- v = (UA_Double)*(const UA_UInt32*)data1 - (UA_Double)*(const UA_UInt32*)data2;
- } else if(type == &UA_TYPES[UA_TYPES_INT64]) {
- v = (UA_Double)*(const UA_Int64*)data1 - (UA_Double)*(const UA_Int64*)data2;
- } else if(type == &UA_TYPES[UA_TYPES_UINT64]) {
- v = (UA_Double)*(const UA_UInt64*)data1 - (UA_Double)*(const UA_UInt64*)data2;
- } else if(type == &UA_TYPES[UA_TYPES_FLOAT]) {
- v = (UA_Double)*(const UA_Float*)data1 - (UA_Double)*(const UA_Float*)data2;
- } else if(type == &UA_TYPES[UA_TYPES_DOUBLE]) {
- v = (UA_Double)*(const UA_Double*)data1 - (UA_Double)*(const UA_Double*)data2;
+detectScalarDeadBand(const void *data1, const void *data2,
+ const UA_DataType *type, const UA_Double deadband) {
+ if(type->typeKind == UA_DATATYPEKIND_SBYTE) {
+ UA_DETECT_DEADBAND(UA_SByte);
+ } else if(type->typeKind == UA_DATATYPEKIND_BYTE) {
+ UA_DETECT_DEADBAND(UA_Byte);
+ } else if(type->typeKind == UA_DATATYPEKIND_INT16) {
+ UA_DETECT_DEADBAND(UA_Int16);
+ } else if(type->typeKind == UA_DATATYPEKIND_UINT16) {
+ UA_DETECT_DEADBAND(UA_UInt16);
+ } else if(type->typeKind == UA_DATATYPEKIND_INT32) {
+ UA_DETECT_DEADBAND(UA_Int32);
+ } else if(type->typeKind == UA_DATATYPEKIND_UINT32) {
+ UA_DETECT_DEADBAND(UA_UInt32);
+ } else if(type->typeKind == UA_DATATYPEKIND_INT64) {
+ UA_DETECT_DEADBAND(UA_Int64);
+ } else if(type->typeKind == UA_DATATYPEKIND_UINT64) {
+ UA_DETECT_DEADBAND(UA_UInt64);
+ } else if(type->typeKind == UA_DATATYPEKIND_FLOAT) {
+ UA_DETECT_DEADBAND(UA_Float);
+ } else if(type->typeKind == UA_DATATYPEKIND_DOUBLE) {
+ UA_DETECT_DEADBAND(UA_Double);
} else {
- return false;
+ return false; /* Not a known numerical type */
}
- if(v < 0.0)
- v = -v;
- return (v > deadband);
}
static UA_Boolean
-updateNeededForFilteredValue(const UA_Variant *value, const UA_Variant *oldValue,
- const UA_Double deadbandValue) {
+detectVariantDeadband(const UA_Variant *value, const UA_Variant *oldValue,
+ const UA_Double deadbandValue) {
if(value->arrayLength != oldValue->arrayLength)
return true;
-
if(value->type != oldValue->type)
return true;
-
size_t length = 1;
if(!UA_Variant_isScalar(value))
length = value->arrayLength;
uintptr_t data = (uintptr_t)value->data;
+ uintptr_t oldData = (uintptr_t)oldValue->data;
+ UA_UInt32 memSize = value->type->memSize;
for(size_t i = 0; i < length; ++i) {
- if(outOfDeadBand((const void*)data, oldValue->data, value->type, deadbandValue))
+ if(detectScalarDeadBand((const void*)data, (const void*)oldData,
+ value->type, deadbandValue))
return true;
- data += value->type->memSize;
+ data += memSize;
+ oldData += memSize;
}
-
return false;
}
-/* When a change is detected, encoding contains the heap-allocated binary
- * encoded value. The default for changed is false. */
-static UA_StatusCode
-detectValueChangeWithFilter(UA_Server *server, UA_Session *session, UA_MonitoredItem *mon,
- UA_DataValue *value, UA_ByteString *encoding, UA_Boolean *changed) {
- /* Check for absolute deadband */
- if(UA_DataType_isNumeric(value->value.type) &&
- mon->filter.dataChangeFilter.deadbandType == UA_DEADBANDTYPE_ABSOLUTE) {
- UA_assert(value->value.type);
- if(mon->filter.dataChangeFilter.trigger == UA_DATACHANGETRIGGER_STATUSVALUE ||
- mon->filter.dataChangeFilter.trigger == UA_DATACHANGETRIGGER_STATUSVALUETIMESTAMP) {
- if(!updateNeededForFilteredValue(&value->value, &mon->lastValue,
- mon->filter.dataChangeFilter.deadbandValue))
- return UA_STATUSCODE_GOOD;
- }
- }
-
- /* Stack-allocate some memory for the value encoding. We might heap-allocate
- * more memory if needed. This is just enough for scalars and small
- * structures. */
- UA_STACKARRAY(UA_Byte, stackValueEncoding, UA_VALUENCODING_MAXSTACK);
- UA_ByteString valueEncoding;
- valueEncoding.data = stackValueEncoding;
- valueEncoding.length = UA_VALUENCODING_MAXSTACK;
-
- /* Encode the value */
- UA_Byte *bufPos = valueEncoding.data;
- const UA_Byte *bufEnd = &valueEncoding.data[valueEncoding.length];
- UA_StatusCode retval = UA_encodeBinary(value, &UA_TYPES[UA_TYPES_DATAVALUE],
- &bufPos, &bufEnd, NULL, NULL);
- if(retval == UA_STATUSCODE_BADENCODINGERROR) {
- size_t binsize = UA_calcSizeBinary(value, &UA_TYPES[UA_TYPES_DATAVALUE]);
- if(binsize == 0)
- return UA_STATUSCODE_BADENCODINGERROR;
+static UA_Boolean
+detectValueChange(UA_Server *server, UA_MonitoredItem *mon,
+ const UA_DataValue *value) {
+ UA_LOCK_ASSERT(&server->serviceMutex, 1);
- if(binsize > UA_VALUENCODING_MAXSTACK) {
- retval = UA_ByteString_allocBuffer(&valueEncoding, binsize);
- if(retval == UA_STATUSCODE_GOOD) {
- bufPos = valueEncoding.data;
- bufEnd = &valueEncoding.data[valueEncoding.length];
- retval = UA_encodeBinary(value, &UA_TYPES[UA_TYPES_DATAVALUE],
- &bufPos, &bufEnd, NULL, NULL);
- }
- }
- }
- if(retval != UA_STATUSCODE_GOOD) {
- if(valueEncoding.data != stackValueEncoding)
- UA_ByteString_clear(&valueEncoding);
- return retval;
+ /* Status changes are always reported */
+ if(value->hasStatus != mon->lastValue.hasStatus ||
+ value->status != mon->lastValue.status) {
+ return true;
}
- /* Has the value changed? */
- valueEncoding.length = (uintptr_t)bufPos - (uintptr_t)valueEncoding.data;
- *changed = (!mon->lastSampledValue.data ||
- !UA_String_equal(&valueEncoding, &mon->lastSampledValue));
-
- /* No change */
- if(!(*changed)) {
- if(valueEncoding.data != stackValueEncoding)
- UA_ByteString_clear(&valueEncoding);
- return UA_STATUSCODE_GOOD;
- }
+ /* Default trigger is Status + Value */
+ UA_DataChangeTrigger trigger = UA_DATACHANGETRIGGER_STATUSVALUE;
- /* Change detected. Copy encoding on the heap if necessary. */
- if(valueEncoding.data == stackValueEncoding)
- return UA_ByteString_copy(&valueEncoding, encoding);
+ /* Use the configured trigger */
+ const UA_DataChangeFilter *dcf = NULL;
+ const UA_ExtensionObject *filter = &mon->parameters.filter;
+ if(filter->content.decoded.type == &UA_TYPES[UA_TYPES_DATACHANGEFILTER]) {
+ dcf = (UA_DataChangeFilter*)filter->content.decoded.data;
+ trigger = dcf->trigger;
+ }
- *encoding = valueEncoding;
- return UA_STATUSCODE_GOOD;
-}
+ /* The status was already tested above */
+ if(trigger == UA_DATACHANGETRIGGER_STATUS)
+ return false;
-/* Has this sample changed from the last one? The method may allocate additional
- * space for the encoding buffer. Detect the change in encoding->data. */
-static UA_StatusCode
- detectValueChange(UA_Server *server, UA_Session *session, UA_MonitoredItem *mon,
- UA_DataValue value, UA_ByteString *encoding, UA_Boolean *changed) {
- UA_LOCK_ASSERT(server->serviceMutex, 1);
+ UA_assert(trigger == UA_DATACHANGETRIGGER_STATUSVALUE ||
+ trigger == UA_DATACHANGETRIGGER_STATUSVALUETIMESTAMP);
- /* Apply Filter */
- if(mon->filter.dataChangeFilter.trigger == UA_DATACHANGETRIGGER_STATUS)
- value.hasValue = false;
+ /* Test absolute deadband */
+ if(dcf && dcf->deadbandType == UA_DEADBANDTYPE_ABSOLUTE &&
+ value->value.type != NULL && UA_DataType_isNumeric(value->value.type))
+ return detectVariantDeadband(&value->value, &mon->lastValue.value,
+ dcf->deadbandValue);
- value.hasServerTimestamp = false;
- value.hasServerPicoseconds = false;
- if(mon->filter.dataChangeFilter.trigger < UA_DATACHANGETRIGGER_STATUSVALUETIMESTAMP) {
- value.hasSourceTimestamp = false;
- value.hasSourcePicoseconds = false;
+ /* Compare the source timestamp if the trigger requires that */
+ if(trigger == UA_DATACHANGETRIGGER_STATUSVALUETIMESTAMP) {
+ if(value->hasSourceTimestamp != mon->lastValue.hasSourceTimestamp)
+ return true;
+ if(value->hasSourceTimestamp &&
+ value->sourceTimestamp != mon->lastValue.sourceTimestamp)
+ return true;
}
- /* Detect the value change */
- return detectValueChangeWithFilter(server, session, mon, &value, encoding, changed);
+ /* Has the value changed? */
+ if(value->hasValue != mon->lastValue.hasValue)
+ return true;
+ return (UA_order(&value->value, &mon->lastValue.value,
+ &UA_TYPES[UA_TYPES_VARIANT]) != UA_ORDER_EQ);
}
-/* movedValue returns whether the sample was moved to the notification. The
- * default is false. */
-static UA_StatusCode
-sampleCallbackWithValue(UA_Server *server, UA_Session *session,
- UA_Subscription *sub, UA_MonitoredItem *mon,
- UA_DataValue *value, UA_Boolean *movedValue) {
- UA_assert(mon->attributeId != UA_ATTRIBUTEID_EVENTNOTIFIER);
-
- /* Contains heap-allocated binary encoding of the value if a change was detected */
- UA_ByteString binValueEncoding = UA_BYTESTRING_NULL;
+UA_StatusCode
+UA_MonitoredItem_createDataChangeNotification(UA_Server *server, UA_Subscription *sub,
+ UA_MonitoredItem *mon,
+ const UA_DataValue *value) {
+ /* Allocate a new notification */
+ UA_Notification *newNotification = UA_Notification_new();
+ if(!newNotification)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
- /* Has the value changed? Allocates memory in binValueEncoding if necessary.
- * value is edited internally so we make a shallow copy. */
- UA_Boolean changed = false;
- UA_StatusCode retval = detectValueChange(server, session, mon, *value, &binValueEncoding, &changed);
+ /* Prepare the notification */
+ newNotification->mon = mon;
+ newNotification->data.dataChange.clientHandle = mon->parameters.clientHandle;
+ UA_StatusCode retval = UA_DataValue_copy(value, &newNotification->data.dataChange.value);
if(retval != UA_STATUSCODE_GOOD) {
- UA_LOG_WARNING_SESSION(&server->config.logger, session, "Subscription %" PRIu32 " | "
- "MonitoredItem %" PRIi32 " | Value change detection failed with StatusCode %s",
- sub ? sub->subscriptionId : 0, mon->monitoredItemId,
- UA_StatusCode_name(retval));
+ UA_free(newNotification);
return retval;
}
+
+ /* Enqueue the notification */
+ UA_assert(sub);
+ UA_Notification_enqueueAndTrigger(server, newNotification);
+ return UA_STATUSCODE_GOOD;
+}
+
+/* Moves the value to the MonitoredItem if successful */
+UA_StatusCode
+sampleCallbackWithValue(UA_Server *server, UA_Subscription *sub,
+ UA_MonitoredItem *mon, UA_DataValue *value) {
+ UA_assert(mon->itemToMonitor.attributeId != UA_ATTRIBUTEID_EVENTNOTIFIER);
+
+ /* Has the value changed (with the filters applied)? */
+ UA_Boolean changed = detectValueChange(server, mon, value);
if(!changed) {
- UA_LOG_DEBUG_SESSION(&server->config.logger, session, "Subscription %" PRIu32 " | "
- "MonitoredItem %" PRIi32 " | The value has not changed",
- sub ? sub->subscriptionId : 0, mon->monitoredItemId);
+ UA_LOG_DEBUG_SUBSCRIPTION(&server->config.logger, sub,
+ "MonitoredItem %" PRIi32 " | "
+ "The value has not changed", mon->monitoredItemId);
+ UA_DataValue_clear(value);
return UA_STATUSCODE_GOOD;
}
/* The MonitoredItem is attached to a subscription (not server-local).
* Prepare a notification and enqueue it. */
if(sub) {
- /* Allocate a new notification */
- UA_Notification *newNotification = (UA_Notification *)UA_malloc(sizeof(UA_Notification));
- if(!newNotification) {
- UA_ByteString_clear(&binValueEncoding);
- return UA_STATUSCODE_BADOUTOFMEMORY;
- }
-
- if(value->value.storageType == UA_VARIANT_DATA) {
- newNotification->data.value = *value; /* Move the value to the notification */
- *movedValue = true;
- } else { /* => (value->value.storageType == UA_VARIANT_DATA_NODELETE) */
- retval = UA_DataValue_copy(value, &newNotification->data.value);
- if(retval != UA_STATUSCODE_GOOD) {
- UA_ByteString_clear(&binValueEncoding);
- UA_free(newNotification);
- return retval;
- }
- }
-
- /* <-- Point of no return --> */
-
- UA_LOG_DEBUG_SESSION(&server->config.logger, session, "Subscription %" PRIu32 " | "
- "MonitoredItem %" PRIi32 " | Enqueue a new notification",
- sub ? sub->subscriptionId : 0, mon->monitoredItemId);
-
- newNotification->mon = mon;
- UA_Notification_enqueue(server, sub, mon, newNotification);
+ UA_StatusCode retval =
+ UA_MonitoredItem_createDataChangeNotification(server, sub, mon, value);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
}
- /* Store the encoding for comparison */
- UA_ByteString_clear(&mon->lastSampledValue);
- mon->lastSampledValue = binValueEncoding;
+ /* <-- Point of no return --> */
- /* Store the value for filter comparison (we don't want to decode
- * lastSampledValue in every iteration). Don't test the return code here. If
- * this fails, lastValue is empty and a notification will be forced for the
- * next deadband comparison. */
- if((mon->filter.dataChangeFilter.deadbandType == UA_DEADBANDTYPE_NONE ||
- mon->filter.dataChangeFilter.deadbandType == UA_DEADBANDTYPE_ABSOLUTE ||
- mon->filter.dataChangeFilter.deadbandType == UA_DEADBANDTYPE_PERCENT) &&
- (mon->filter.dataChangeFilter.trigger == UA_DATACHANGETRIGGER_STATUS ||
- mon->filter.dataChangeFilter.trigger == UA_DATACHANGETRIGGER_STATUSVALUE ||
- mon->filter.dataChangeFilter.trigger == UA_DATACHANGETRIGGER_STATUSVALUETIMESTAMP)) {
- UA_Variant_clear(&mon->lastValue);
- UA_Variant_copy(&value->value, &mon->lastValue);
-#ifdef UA_ENABLE_DA
- mon->lastStatus = value->status;
-#endif
- }
+ /* Move/store the value for filter comparison and TransferSubscription */
+ UA_DataValue_clear(&mon->lastValue);
+ mon->lastValue = *value;
/* Call the local callback if the MonitoredItem is not attached to a
* subscription. Do this at the very end. Because the callback might delete
@@ -54681,121 +60188,73 @@ sampleCallbackWithValue(UA_Server *server, UA_Session *session,
if(!sub) {
UA_LocalMonitoredItem *localMon = (UA_LocalMonitoredItem*) mon;
void *nodeContext = NULL;
- getNodeContext(server, mon->monitoredNodeId, &nodeContext);
- UA_UNLOCK(server->serviceMutex);
- localMon->callback.dataChangeCallback(server, mon->monitoredItemId,
- localMon->context,
- &mon->monitoredNodeId,
- nodeContext, mon->attributeId,
- value);
- UA_LOCK(server->serviceMutex);
+ getNodeContext(server, mon->itemToMonitor.nodeId, &nodeContext);
+ UA_UNLOCK(&server->serviceMutex);
+ localMon->callback.dataChangeCallback(server,
+ mon->monitoredItemId, localMon->context,
+ &mon->itemToMonitor.nodeId, nodeContext,
+ mon->itemToMonitor.attributeId, value);
+ UA_LOCK(&server->serviceMutex);
}
return UA_STATUSCODE_GOOD;
}
void
-UA_MonitoredItem_sampleCallback(UA_Server *server, UA_MonitoredItem *monitoredItem)
-{
- UA_LOCK(server->serviceMutex);
+UA_MonitoredItem_sampleCallback(UA_Server *server, UA_MonitoredItem *monitoredItem) {
+ UA_LOCK(&server->serviceMutex);
monitoredItem_sampleCallback(server, monitoredItem);
- UA_UNLOCK(server->serviceMutex)
+ UA_UNLOCK(&server->serviceMutex);
}
void
monitoredItem_sampleCallback(UA_Server *server, UA_MonitoredItem *monitoredItem) {
- UA_LOCK_ASSERT(server->serviceMutex, 1);
+ UA_LOCK_ASSERT(&server->serviceMutex, 1);
UA_Subscription *sub = monitoredItem->subscription;
UA_Session *session = &server->adminSession;
if(sub)
session = sub->session;
- UA_LOG_DEBUG_SESSION(&server->config.logger, session, "Subscription %" PRIu32 " | "
- "MonitoredItem %" PRIi32 " | Sample callback called",
- sub ? sub->subscriptionId : 0, monitoredItem->monitoredItemId);
-
- UA_assert(monitoredItem->attributeId != UA_ATTRIBUTEID_EVENTNOTIFIER);
+ UA_LOG_DEBUG_SUBSCRIPTION(&server->config.logger, sub,
+ "MonitoredItem %" PRIi32 " | "
+ "Sample callback called", monitoredItem->monitoredItemId);
- /* Get the node */
- const UA_Node *node = UA_NODESTORE_GET(server, &monitoredItem->monitoredNodeId);
+ UA_assert(monitoredItem->itemToMonitor.attributeId != UA_ATTRIBUTEID_EVENTNOTIFIER);
/* Sample the value. The sample can still point into the node. */
- UA_DataValue value;
- UA_DataValue_init(&value);
- if(node) {
- UA_ReadValueId rvid;
- UA_ReadValueId_init(&rvid);
- rvid.nodeId = monitoredItem->monitoredNodeId;
- rvid.attributeId = monitoredItem->attributeId;
- rvid.indexRange = monitoredItem->indexRange;
- ReadWithNode(node, server, session, monitoredItem->timestampsToReturn, &rvid, &value);
- } else {
- value.hasStatus = true;
- value.status = UA_STATUSCODE_BADNODEIDUNKNOWN;
- }
+ UA_DataValue value = UA_Server_readWithSession(server, session,
+ &monitoredItem->itemToMonitor,
+ monitoredItem->timestampsToReturn);
- /* Operate on the sample */
- UA_Boolean movedValue = false;
- UA_StatusCode retval = sampleCallbackWithValue(server, session, sub, monitoredItem, &value, &movedValue);
- if(retval != UA_STATUSCODE_GOOD) {
- UA_LOG_WARNING_SESSION(&server->config.logger, session, "Subscription %" PRIu32 " | "
- "MonitoredItem %" PRIi32 " | Sampling returned the statuscode %s",
- sub ? sub->subscriptionId : 0, monitoredItem->monitoredItemId,
- UA_StatusCode_name(retval));
+ /* Operate on the sample. The sample is consumed when the status is good. */
+ UA_StatusCode res = sampleCallbackWithValue(server, sub, monitoredItem, &value);
+ if(res != UA_STATUSCODE_GOOD) {
+ UA_DataValue_clear(&value);
+ UA_LOG_WARNING_SUBSCRIPTION(&server->config.logger, sub,
+ "MonitoredItem %" PRIi32 " | "
+ "Sampling returned the statuscode %s",
+ monitoredItem->monitoredItemId,
+ UA_StatusCode_name(res));
}
-
- /* Delete the sample if it was not moved to the notification. */
- if(!movedValue)
- UA_DataValue_clear(&value); /* Does nothing for UA_VARIANT_DATA_NODELETE */
- if(node)
- UA_NODESTORE_RELEASE(server, node);
}
#endif /* UA_ENABLE_SUBSCRIPTIONS */
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/src/server/ua_subscription_events.c" ***********************************/
+/**** amalgamated original file "/src/server/ua_subscription_events.c" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Copyright 2018 (c) Ari Breitkreuz, fortiss GmbH
- * Copyright 2020 (c) Christian von Arnim
+ * Copyright 2020 (c) Christian von Arnim, ISW University of Stuttgart (for VDW and umati)
+ * Copyright 2021 (c) Fraunhofer IOSB (Author: Andreas Ebner)
*/
#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
-UA_StatusCode
-UA_MonitoredItem_removeNodeEventCallback(UA_Server *server, UA_Session *session,
- UA_Node *node, void *data) {
- if (node->nodeClass != UA_NODECLASS_OBJECT)
- return UA_STATUSCODE_BADINVALIDARGUMENT;
- UA_ObjectNode *on = (UA_ObjectNode*)node;
- UA_MonitoredItem *remove = (UA_MonitoredItem*)data;
-
- if(!on->monitoredItemQueue)
- return UA_STATUSCODE_GOOD;
-
- /* Edge case that it's the first element */
- if(on->monitoredItemQueue == remove) {
- on->monitoredItemQueue = remove->next;
- return UA_STATUSCODE_GOOD;
- }
-
- UA_MonitoredItem *prev = on->monitoredItemQueue;
- UA_MonitoredItem *entry = prev->next;
- for(; entry != NULL; prev = entry, entry = entry->next) {
- if(entry == remove) {
- prev->next = entry->next;
- return UA_STATUSCODE_GOOD;
- }
- }
-
- return UA_STATUSCODE_BADNOTFOUND;
-}
-
/* We use a 16-Byte ByteString as an identifier */
UA_StatusCode
UA_Event_generateEventId(UA_ByteString *generatedId) {
@@ -54815,28 +60274,28 @@ UA_Event_generateEventId(UA_ByteString *generatedId) {
UA_StatusCode
UA_Server_createEvent(UA_Server *server, const UA_NodeId eventType,
UA_NodeId *outNodeId) {
- UA_LOCK(server->serviceMutex);
+ UA_LOCK(&server->serviceMutex);
if(!outNodeId) {
UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_USERLAND,
"outNodeId must not be NULL. The event's NodeId must be returned "
"so it can be triggered.");
- UA_UNLOCK(server->serviceMutex);
+ UA_UNLOCK(&server->serviceMutex);
return UA_STATUSCODE_BADINVALIDARGUMENT;
}
/* Make sure the eventType is a subtype of BaseEventType */
- UA_NodeId hasSubtypeId = UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE);
UA_NodeId baseEventTypeId = UA_NODEID_NUMERIC(0, UA_NS0ID_BASEEVENTTYPE);
- if(!isNodeInTree(server, &eventType, &baseEventTypeId, &hasSubtypeId, 1)) {
+ if(!isNodeInTree_singleRef(server, &eventType, &baseEventTypeId,
+ UA_REFERENCETYPEINDEX_HASSUBTYPE)) {
UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_USERLAND,
"Event type must be a subtype of BaseEventType!");
- UA_UNLOCK(server->serviceMutex);
+ UA_UNLOCK(&server->serviceMutex);
return UA_STATUSCODE_BADINVALIDARGUMENT;
}
/* Create an ObjectNode which represents the event */
UA_QualifiedName name;
- // set a dummy name. This is not used.
+ /* set a dummy name. This is not used. */
name = UA_QUALIFIEDNAME(0,"E");
UA_NodeId newNodeId = UA_NODEID_NULL;
UA_ObjectAttributes oAttr = UA_ObjectAttributes_default;
@@ -54853,6 +60312,7 @@ UA_Server_createEvent(UA_Server *server, const UA_NodeId eventType,
if(retval != UA_STATUSCODE_GOOD) {
UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_USERLAND,
"Adding event failed. StatusCode %s", UA_StatusCode_name(retval));
+ UA_UNLOCK(&server->serviceMutex);
return retval;
}
@@ -54864,7 +60324,7 @@ UA_Server_createEvent(UA_Server *server, const UA_NodeId eventType,
UA_BrowsePathResult_clear(&bpr);
deleteNode(server, newNodeId, true);
UA_NodeId_clear(&newNodeId);
- UA_UNLOCK(server->serviceMutex);
+ UA_UNLOCK(&server->serviceMutex);
return retval;
}
@@ -54872,311 +60332,18 @@ UA_Server_createEvent(UA_Server *server, const UA_NodeId eventType,
UA_Variant value;
UA_Variant_init(&value);
UA_Variant_setScalar(&value, (void*)(uintptr_t)&eventType, &UA_TYPES[UA_TYPES_NODEID]);
- retval = writeWithWriteValue(server, &bpr.targets[0].targetId.nodeId, UA_ATTRIBUTEID_VALUE, &UA_TYPES[UA_TYPES_VARIANT], &value);
+ retval = writeValueAttribute(server, &server->adminSession,
+ &bpr.targets[0].targetId.nodeId, &value);
UA_BrowsePathResult_clear(&bpr);
if(retval != UA_STATUSCODE_GOOD) {
deleteNode(server, newNodeId, true);
UA_NodeId_clear(&newNodeId);
- UA_UNLOCK(server->serviceMutex);
+ UA_UNLOCK(&server->serviceMutex);
return retval;
}
*outNodeId = newNodeId;
- UA_UNLOCK(server->serviceMutex);
- return UA_STATUSCODE_GOOD;
-}
-
-static UA_Boolean
-isValidEvent(UA_Server *server, const UA_NodeId *validEventParent,
- const UA_NodeId *eventId) {
- /* find the eventType variableNode */
- UA_QualifiedName findName = UA_QUALIFIEDNAME(0, "EventType");
- UA_BrowsePathResult bpr = browseSimplifiedBrowsePath(server, *eventId, 1, &findName);
- if(bpr.statusCode != UA_STATUSCODE_GOOD || bpr.targetsSize < 1) {
- UA_BrowsePathResult_clear(&bpr);
- return false;
- }
-
- /* Get the EventType Property Node */
- UA_Variant tOutVariant;
- UA_Variant_init(&tOutVariant);
-
- /* Read the Value of EventType Property Node (the Value should be a NodeId) */
- UA_StatusCode retval = readWithReadValue(server, &bpr.targets[0].targetId.nodeId,
- UA_ATTRIBUTEID_VALUE, &tOutVariant);
- if(retval != UA_STATUSCODE_GOOD ||
- !UA_Variant_hasScalarType(&tOutVariant, &UA_TYPES[UA_TYPES_NODEID])) {
- UA_BrowsePathResult_clear(&bpr);
- return false;
- }
-
- const UA_NodeId *tEventType = (UA_NodeId*)tOutVariant.data;
-
- /* check whether the EventType is a Subtype of CondtionType
- * (Part 9 first implementation) */
- UA_NodeId conditionTypeId = UA_NODEID_NUMERIC(0, UA_NS0ID_CONDITIONTYPE);
- UA_NodeId hasSubtypeId = UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE);
-
- if(UA_NodeId_equal(validEventParent, &conditionTypeId) &&
- isNodeInTree(server, tEventType,
- &conditionTypeId, &hasSubtypeId, 1)){
- UA_BrowsePathResult_deleteMembers(&bpr);
- UA_Variant_clear(&tOutVariant);
- return true;
- }
-
- /*EventType is not a Subtype of CondtionType
- *(ConditionId Clause won't be present in Events, which are not Conditions)*/
- /* check whether Valid Event other than Conditions */
- UA_NodeId baseEventTypeId = UA_NODEID_NUMERIC(0, UA_NS0ID_BASEEVENTTYPE);
- UA_Boolean isSubtypeOfBaseEvent = isNodeInTree(server, tEventType,
- &baseEventTypeId, &hasSubtypeId, 1);
-
- UA_BrowsePathResult_clear(&bpr);
- UA_Variant_clear(&tOutVariant);
- return isSubtypeOfBaseEvent;
-}
-
-/* Part 4: 7.4.4.5 SimpleAttributeOperand
- * The clause can point to any attribute of nodes. Either a child of the event
- * node and also the event type. */
-static UA_StatusCode
-resolveSimpleAttributeOperand(UA_Server *server, UA_Session *session, const UA_NodeId *origin,
- const UA_SimpleAttributeOperand *sao, UA_Variant *value) {
- /* Prepare the ReadValueId */
- UA_ReadValueId rvi;
- UA_ReadValueId_init(&rvi);
- rvi.indexRange = sao->indexRange;
- rvi.attributeId = sao->attributeId;
-
- /* If this list (browsePath) is empty the Node is the instance of the
- * TypeDefinition. */
- if(sao->browsePathSize == 0) {
- UA_NodeId conditionTypeId = UA_NODEID_NUMERIC(0, UA_NS0ID_CONDITIONTYPE);
-
-#ifdef UA_ENABLE_SUBSCRIPTIONS_ALARMS_CONDITIONS
- //TODO check for Branches! One Condition could have multiple Branches
- // Set ConditionId
- if(UA_NodeId_equal(&sao->typeDefinitionId, &conditionTypeId)){
- UA_NodeId conditionId;
- UA_StatusCode retval = UA_getConditionId(server, origin, &conditionId);
- if(retval != UA_STATUSCODE_GOOD)
- return retval;
-
- rvi.nodeId = conditionId;
- }
- else
- rvi.nodeId = sao->typeDefinitionId;
-#else
- if(UA_NodeId_equal(&sao->typeDefinitionId, &conditionTypeId))
- return UA_STATUSCODE_BADNOTSUPPORTED;
- else
- rvi.nodeId = sao->typeDefinitionId;
-#endif /*UA_ENABLE_SUBSCRIPTIONS_ALARMS_CONDITIONS*/
- UA_DataValue v = UA_Server_readWithSession(server, session, &rvi,
- UA_TIMESTAMPSTORETURN_NEITHER);
- if(v.status == UA_STATUSCODE_GOOD && v.hasValue)
- *value = v.value;
- return v.status;
- }
-
- /* Resolve the browse path */
- UA_BrowsePathResult bpr =
- browseSimplifiedBrowsePath(server, *origin, sao->browsePathSize, sao->browsePath);
- if(bpr.targetsSize == 0 && bpr.statusCode == UA_STATUSCODE_GOOD)
- bpr.statusCode = UA_STATUSCODE_BADNOTFOUND;
- if(bpr.statusCode != UA_STATUSCODE_GOOD) {
- UA_StatusCode retval = bpr.statusCode;
- UA_BrowsePathResult_clear(&bpr);
- return retval;
- }
-
- /* Read the first matching element. Move the value to the output. */
- rvi.nodeId = bpr.targets[0].targetId.nodeId;
- UA_DataValue v = UA_Server_readWithSession(server, session, &rvi,
- UA_TIMESTAMPSTORETURN_NEITHER);
- if(v.status == UA_STATUSCODE_GOOD && v.hasValue)
- *value = v.value;
-
- UA_BrowsePathResult_clear(&bpr);
- return v.status;
-}
-
-UA_StatusCode
-UA_Server_evaluateWhereClauseContentFilter(
- UA_Server *server,
- const UA_NodeId *eventNode,
- const UA_ContentFilter *contentFilter) {
- if(contentFilter->elements == NULL || contentFilter->elementsSize == 0)
- {
- /* Nothing to do.*/
- /** @todo Whats the default result?*/
- return UA_STATUSCODE_GOOD;
- }
-
- /* The first element needs to be evaluated, this might be linked to */
- /* other elements, which are evaluated in these cases.*/
- /* See 7.4.1 in Part 4, v1.04-Nov 22, 2017 */
- UA_ContentFilterElement *pElement = &contentFilter->elements[0];
- /** @todo Verify retun types in specification or CTT */
- switch (pElement->filterOperator)
- {
- case UA_FILTEROPERATOR_INVIEW:
- case UA_FILTEROPERATOR_RELATEDTO:
- {
- /*Not allowed for event WhereClause according to 7.17.3 in */
- /* Part 4, v1.04-Nov 22, 2017*/
- return UA_STATUSCODE_BADEVENTFILTERINVALID;
- }
- case UA_FILTEROPERATOR_EQUALS:
- case UA_FILTEROPERATOR_ISNULL:
- case UA_FILTEROPERATOR_GREATERTHAN:
- case UA_FILTEROPERATOR_LESSTHAN:
- case UA_FILTEROPERATOR_GREATERTHANOREQUAL:
- case UA_FILTEROPERATOR_LESSTHANOREQUAL:
- case UA_FILTEROPERATOR_LIKE:
- case UA_FILTEROPERATOR_NOT:
- case UA_FILTEROPERATOR_BETWEEN:
- case UA_FILTEROPERATOR_INLIST:
- case UA_FILTEROPERATOR_AND:
- case UA_FILTEROPERATOR_OR:
- case UA_FILTEROPERATOR_CAST:
- case UA_FILTEROPERATOR_BITWISEAND:
- case UA_FILTEROPERATOR_BITWISEOR:
- {
- return UA_STATUSCODE_BADFILTEROPERATORUNSUPPORTED;
- }
- case UA_FILTEROPERATOR_OFTYPE:
- {
- UA_Boolean result = UA_FALSE;
- if(pElement->filterOperandsSize != 1)
- {
- return UA_STATUSCODE_BADFILTEROPERANDCOUNTMISMATCH;
- }
- if(pElement->filterOperands[0].content.decoded.type !=
- &UA_TYPES[UA_TYPES_LITERALOPERAND])
- {
- return UA_STATUSCODE_BADFILTEROPERATORUNSUPPORTED;
- }
- UA_LiteralOperand *pOperand =
- (UA_LiteralOperand *) pElement->filterOperands[0].content.decoded.data;
- if(!UA_Variant_isScalar(&pOperand->value))
- {
- return UA_STATUSCODE_BADEVENTFILTERINVALID;
- }
-
- if(pOperand->value.type != &UA_TYPES[UA_TYPES_NODEID]
- || pOperand->value.data == NULL)
- {
- result = UA_FALSE;
- }
- else {
- UA_NodeId *pOperandNodeId = (UA_NodeId *) pOperand->value.data;
- UA_NodeId hasSubtypeId =
- UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE);
- UA_QualifiedName eventTypeQualifiedName =
- UA_QUALIFIEDNAME(0, "EventType");
- UA_Variant typeNodeIdVariant;
- UA_Variant_init(&typeNodeIdVariant);
- UA_StatusCode readStatusCode =
- readObjectProperty(
- server, *eventNode,
- eventTypeQualifiedName, &typeNodeIdVariant);
- if(readStatusCode != UA_STATUSCODE_GOOD)
- {
- return readStatusCode;
- }
-
- if(!UA_Variant_isScalar(&typeNodeIdVariant)
- || typeNodeIdVariant.type != &UA_TYPES[UA_TYPES_NODEID]
- || typeNodeIdVariant.data == NULL)
- {
- UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
- "EventType has an invalid type.");
- UA_Variant_clear(&typeNodeIdVariant);
- return UA_STATUSCODE_BADINTERNALERROR;
- }
- result = isNodeInTree(
- server, (UA_NodeId*) typeNodeIdVariant.data,
- pOperandNodeId, &hasSubtypeId, 1);
- UA_Variant_clear(&typeNodeIdVariant);
- }
-
- if(result)
- {
- return UA_STATUSCODE_GOOD;
- }
- else
- {
- return UA_STATUSCODE_BADNOMATCH;
- }
- }
- break;
- default:
- return UA_STATUSCODE_BADFILTEROPERATORINVALID;
- break;
- }
-}
-
-/* Filters the given event with the given filter and writes the results into a
- * notification */
-static UA_StatusCode
-UA_Server_filterEvent(UA_Server *server, UA_Session *session,
- const UA_NodeId *eventNode, UA_EventFilter *filter,
- UA_EventNotification *notification) {
- if (filter->selectClausesSize == 0)
- return UA_STATUSCODE_BADEVENTFILTERINVALID;
-
- UA_StatusCode retVal = UA_Server_evaluateWhereClauseContentFilter(
- server, eventNode, &filter->whereClause);
- if(retVal != UA_STATUSCODE_GOOD)
- {
- return retVal;
- }
- UA_EventFieldList_init(&notification->fields);
- /* EventFilterResult isn't being used currently
- UA_EventFilterResult_init(&notification->result); */
-
- notification->fields.eventFields = (UA_Variant *)
- UA_Array_new(filter->selectClausesSize, &UA_TYPES[UA_TYPES_VARIANT]);
- if(!notification->fields.eventFields) {
- /* EventFilterResult currently isn't being used
- UA_EventFiterResult_clear(&notification->result); */
- return UA_STATUSCODE_BADOUTOFMEMORY;
- }
- notification->fields.eventFieldsSize = filter->selectClausesSize;
-
- /* EventFilterResult currently isn't being used
- notification->result.selectClauseResultsSize = filter->selectClausesSize;
- notification->result.selectClauseResults = (UA_StatusCode *)
- UA_Array_new(filter->selectClausesSize, &UA_TYPES[UA_TYPES_STATUSCODE]);
- if(!notification->result->selectClauseResults) {
- UA_EventFieldList_clear(&notification->fields);
- UA_EventFilterResult_clear(&notification->result);
- return UA_STATUSCODE_BADOUTOFMEMORY;
- }
- */
-
- /* Apply the filter */
-
- /* Check if the browsePath is BaseEventType, in which case nothing more
- * needs to be checked */
- UA_NodeId baseEventTypeId = UA_NODEID_NUMERIC(0, UA_NS0ID_BASEEVENTTYPE);
- for(size_t i = 0; i < filter->selectClausesSize; i++) {
- if(!UA_NodeId_equal(&filter->selectClauses[i].typeDefinitionId, &baseEventTypeId) &&
- !isValidEvent(server, &filter->selectClauses[i].typeDefinitionId, eventNode)) {
- UA_Variant_init(&notification->fields.eventFields[i]);
- /* EventFilterResult currently isn't being used
- notification->result.selectClauseResults[i] = UA_STATUSCODE_BADTYPEDEFINITIONINVALID; */
- continue;
- }
-
- /* TODO: Put the result into the selectClausResults */
- resolveSimpleAttributeOperand(server, session, eventNode,
- &filter->selectClauses[i],
- &notification->fields.eventFields[i]);
- }
-
+ UA_UNLOCK(&server->serviceMutex);
return UA_STATUSCODE_GOOD;
}
@@ -55195,8 +60362,8 @@ eventSetStandardFields(UA_Server *server, const UA_NodeId *event,
UA_Variant value;
UA_Variant_init(&value);
UA_Variant_setScalarCopy(&value, origin, &UA_TYPES[UA_TYPES_NODEID]);
- retval = writeWithWriteValue(server, &bpr.targets[0].targetId.nodeId,
- UA_ATTRIBUTEID_VALUE, &UA_TYPES[UA_TYPES_VARIANT], &value);
+ retval = writeValueAttribute(server, &server->adminSession,
+ &bpr.targets[0].targetId.nodeId, &value);
UA_Variant_clear(&value);
UA_BrowsePathResult_clear(&bpr);
if(retval != UA_STATUSCODE_GOOD)
@@ -55212,8 +60379,8 @@ eventSetStandardFields(UA_Server *server, const UA_NodeId *event,
}
UA_DateTime rcvTime = UA_DateTime_now();
UA_Variant_setScalar(&value, &rcvTime, &UA_TYPES[UA_TYPES_DATETIME]);
- retval = writeWithWriteValue(server, &bpr.targets[0].targetId.nodeId,
- UA_ATTRIBUTEID_VALUE, &UA_TYPES[UA_TYPES_VARIANT], &value);
+ retval = writeValueAttribute(server, &server->adminSession,
+ &bpr.targets[0].targetId.nodeId, &value);
UA_BrowsePathResult_clear(&bpr);
if(retval != UA_STATUSCODE_GOOD)
return retval;
@@ -55233,8 +60400,8 @@ eventSetStandardFields(UA_Server *server, const UA_NodeId *event,
}
UA_Variant_init(&value);
UA_Variant_setScalar(&value, &eventId, &UA_TYPES[UA_TYPES_BYTESTRING]);
- retval = writeWithWriteValue(server, &bpr.targets[0].targetId.nodeId,
- UA_ATTRIBUTEID_VALUE, &UA_TYPES[UA_TYPES_VARIANT], &value);
+ retval = writeValueAttribute(server, &server->adminSession,
+ &bpr.targets[0].targetId.nodeId, &value);
UA_BrowsePathResult_clear(&bpr);
if(retval != UA_STATUSCODE_GOOD) {
UA_ByteString_clear(&eventId);
@@ -55253,36 +60420,88 @@ eventSetStandardFields(UA_Server *server, const UA_NodeId *event,
/* Filters an event according to the filter specified by mon and then adds it to
* mons notification queue */
UA_StatusCode
-UA_Event_addEventToMonitoredItem(UA_Server *server, const UA_NodeId *event, UA_MonitoredItem *mon) {
- UA_Notification *notification = (UA_Notification *) UA_malloc(sizeof(UA_Notification));
+UA_Event_addEventToMonitoredItem(UA_Server *server, const UA_NodeId *event,
+ UA_MonitoredItem *mon) {
+ UA_Notification *notification = UA_Notification_new();
if(!notification)
return UA_STATUSCODE_BADOUTOFMEMORY;
- /* Get the session */
- UA_Subscription *sub = mon->subscription;
- UA_Session *session = sub->session;
+ if(mon->parameters.filter.content.decoded.type != &UA_TYPES[UA_TYPES_EVENTFILTER])
+ return UA_STATUSCODE_BADFILTERNOTALLOWED;
+ UA_EventFilter *eventFilter = (UA_EventFilter*)
+ mon->parameters.filter.content.decoded.data;
+ /* The MonitoredItem must be attached to a Subscription. This code path is
+ * not taken for local MonitoredItems (once they are enabled for Events). */
+ UA_Subscription *sub = mon->subscription;
+ UA_assert(sub);
- /* Apply the filter */
- UA_StatusCode retval =
- UA_Server_filterEvent(server, session, event, &mon->filter.eventFilter,
- &notification->data.event);
- if(retval == UA_STATUSCODE_BADNOMATCH)
- {
- UA_free(notification);
- return UA_STATUSCODE_GOOD;
- }
+ UA_Session *session = sub->session;
+ UA_StatusCode retval = filterEvent(server, session, event,
+ eventFilter, &notification->data.event,
+ &notification->result);
if(retval != UA_STATUSCODE_GOOD) {
- UA_free(notification);
+ UA_Notification_delete(notification);
+ if(retval == UA_STATUSCODE_BADNOMATCH)
+ return UA_STATUSCODE_GOOD;
return retval;
}
- /* Enqueue the notification */
+ notification->data.event.clientHandle = mon->parameters.clientHandle;
notification->mon = mon;
- UA_Notification_enqueue(server, mon->subscription, mon, notification);
+
+ UA_Notification_enqueueAndTrigger(server, notification);
return UA_STATUSCODE_GOOD;
}
+#ifdef UA_ENABLE_HISTORIZING
+static void
+setHistoricalEvent(UA_Server *server, const UA_NodeId *origin,
+ const UA_NodeId *emitNodeId, const UA_NodeId *eventNodeId) {
+ UA_Variant historicalEventFilterValue;
+ UA_Variant_init(&historicalEventFilterValue);
+
+ /* A HistoricalEventNode that has event history available will provide this property */
+ UA_StatusCode retval =
+ readObjectProperty(server, *emitNodeId,
+ UA_QUALIFIEDNAME(0, "HistoricalEventFilter"),
+ &historicalEventFilterValue);
+ if(retval != UA_STATUSCODE_GOOD) {
+ /* Do not vex users with no match errors */
+ if(retval != UA_STATUSCODE_BADNOMATCH)
+ UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Cannot read the HistoricalEventFilter property of a "
+ "listening node. StatusCode %s",
+ UA_StatusCode_name(retval));
+ return;
+ }
+
+ /* If found then check if HistoricalEventFilter property has a valid value */
+ if(UA_Variant_isEmpty(&historicalEventFilterValue) ||
+ !UA_Variant_isScalar(&historicalEventFilterValue) ||
+ historicalEventFilterValue.type != &UA_TYPES[UA_TYPES_EVENTFILTER]) {
+ UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "HistoricalEventFilter property of a listening node "
+ "does not have a valid value");
+ UA_Variant_clear(&historicalEventFilterValue);
+ return;
+ }
+
+ /* Finally, if found and valid then filter */
+ UA_EventFilter *filter = (UA_EventFilter*) historicalEventFilterValue.data;
+ UA_EventFieldList efl;
+ UA_EventFilterResult result;
+ retval = filterEvent(server, &server->adminSession,
+ eventNodeId, filter, &efl, &result);
+ if(retval == UA_STATUSCODE_GOOD)
+ server->config.historyDatabase.setEvent(server, server->config.historyDatabase.context,
+ origin, emitNodeId, filter, &efl);
+ UA_EventFilterResult_clear(&result);
+ UA_Variant_clear(&historicalEventFilterValue);
+ UA_EventFieldList_clear(&efl);
+}
+#endif
+
static const UA_NodeId objectsFolderId = {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_OBJECTSFOLDER}};
#define EMIT_REFS_ROOT_COUNT 4
static const UA_NodeId emitReferencesRoots[EMIT_REFS_ROOT_COUNT] =
@@ -55291,18 +60510,20 @@ static const UA_NodeId emitReferencesRoots[EMIT_REFS_ROOT_COUNT] =
{0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_HASEVENTSOURCE}},
{0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_HASNOTIFIER}}};
+static const UA_NodeId isInFolderReferences[2] =
+ {{0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_ORGANIZES}},
+ {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_HASCOMPONENT}}};
+
UA_StatusCode
-UA_Server_triggerEvent(UA_Server *server, const UA_NodeId eventNodeId,
- const UA_NodeId origin, UA_ByteString *outEventId,
- const UA_Boolean deleteEventNode) {
- UA_LOCK(server->serviceMutex);
+triggerEvent(UA_Server *server, const UA_NodeId eventNodeId,
+ const UA_NodeId origin, UA_ByteString *outEventId,
+ const UA_Boolean deleteEventNode) {
+ UA_LOCK_ASSERT(&server->serviceMutex, 1);
-#if UA_LOGLEVEL <= 200
- UA_LOG_NODEID_WRAP(&origin,
- UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER,
- "Events: An event is triggered on node %.*s",
- (int)nodeIdStr.length, nodeIdStr.data));
-#endif
+ UA_LOG_NODEID_DEBUG(&origin,
+ UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Events: An event is triggered on node %.*s",
+ (int)nodeIdStr.length, nodeIdStr.data));
#ifdef UA_ENABLE_SUBSCRIPTIONS_ALARMS_CONDITIONS
UA_Boolean isCallerAC = false;
@@ -55311,40 +60532,48 @@ UA_Server_triggerEvent(UA_Server *server, const UA_NodeId eventNodeId,
UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
"Condition Events: Please use A&C API to trigger Condition Events 0x%08X",
UA_STATUSCODE_BADINVALIDARGUMENT);
- UA_UNLOCK(server->serviceMutex);
return UA_STATUSCODE_BADINVALIDARGUMENT;
}
}
-#endif /*UA_ENABLE_SUBSCRIPTIONS_ALARMS_CONDITIONS*/
+#endif /* UA_ENABLE_SUBSCRIPTIONS_ALARMS_CONDITIONS */
/* Check that the origin node exists */
const UA_Node *originNode = UA_NODESTORE_GET(server, &origin);
if(!originNode) {
UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_USERLAND,
"Origin node for event does not exist.");
- UA_UNLOCK(server->serviceMutex);
return UA_STATUSCODE_BADNOTFOUND;
}
UA_NODESTORE_RELEASE(server, originNode);
/* Make sure the origin is in the ObjectsFolder (TODO: or in the ViewsFolder) */
- if(!isNodeInTree(server, &origin, &objectsFolderId,
- emitReferencesRoots, 2)) { /* Only use Organizes and
- * HasComponent to check if we
- * are below the ObjectsFolder */
+ /* Only use Organizes and HasComponent to check if we are below the ObjectsFolder */
+ UA_StatusCode retval;
+ UA_ReferenceTypeSet refTypes;
+ UA_ReferenceTypeSet_init(&refTypes);
+ for(int i = 0; i < 2; ++i) {
+ UA_ReferenceTypeSet tmpRefTypes;
+ retval = referenceTypeIndices(server, &isInFolderReferences[i], &tmpRefTypes, true);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Events: Could not create the list of references and their subtypes "
+ "with StatusCode %s", UA_StatusCode_name(retval));
+ }
+ refTypes = UA_ReferenceTypeSet_union(refTypes, tmpRefTypes);
+ }
+
+ if(!isNodeInTree(server, &origin, &objectsFolderId, &refTypes)) {
UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_USERLAND,
"Node for event must be in ObjectsFolder!");
- UA_UNLOCK(server->serviceMutex);
return UA_STATUSCODE_BADINVALIDARGUMENT;
}
/* Update the standard fields of the event */
- UA_StatusCode retval = eventSetStandardFields(server, &eventNodeId, &origin, outEventId);
+ retval = eventSetStandardFields(server, &eventNodeId, &origin, outEventId);
if(retval != UA_STATUSCODE_GOOD) {
UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
"Events: Could not set the standard event fields with StatusCode %s",
UA_StatusCode_name(retval));
- UA_UNLOCK(server->serviceMutex);
return retval;
}
@@ -55365,34 +60594,23 @@ UA_Server_triggerEvent(UA_Server *server, const UA_NodeId eventNodeId,
emitStartNodes[1] = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER);
/* Get all ReferenceTypes over which the events propagate */
- UA_NodeId *emitRefTypes[EMIT_REFS_ROOT_COUNT] = {NULL, NULL, NULL};
- size_t emitRefTypesSize[EMIT_REFS_ROOT_COUNT] = {0, 0, 0, 0};
- size_t totalEmitRefTypesSize = 0;
- for (size_t i=0; i<EMIT_REFS_ROOT_COUNT; i++) {
- retval |= referenceSubtypes(server, &emitReferencesRoots[i],
- &emitRefTypesSize[i], &emitRefTypes[i]);
- totalEmitRefTypesSize += emitRefTypesSize[i];
- }
- UA_STACKARRAY(UA_NodeId, totalEmitRefTypes, totalEmitRefTypesSize);
- if(retval != UA_STATUSCODE_GOOD) {
- UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
- "Events: Could not create the list of references for event "
- "propagation with StatusCode %s", UA_StatusCode_name(retval));
- goto cleanup;
- }
-
- size_t currIndex = 0;
- for (size_t i=0; i<EMIT_REFS_ROOT_COUNT; i++) {
- memcpy(&totalEmitRefTypes[currIndex], emitRefTypes[i],
- emitRefTypesSize[i] * sizeof(UA_NodeId));
- currIndex += emitRefTypesSize[i];
+ UA_ReferenceTypeSet emitRefTypes;
+ UA_ReferenceTypeSet_init(&emitRefTypes);
+ for(size_t i = 0; i < EMIT_REFS_ROOT_COUNT; i++) {
+ UA_ReferenceTypeSet tmpRefTypes;
+ retval = referenceTypeIndices(server, &emitReferencesRoots[i], &tmpRefTypes, true);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Events: Could not create the list of references for event "
+ "propagation with StatusCode %s", UA_StatusCode_name(retval));
+ goto cleanup;
+ }
+ emitRefTypes = UA_ReferenceTypeSet_union(emitRefTypes, tmpRefTypes);
}
-
/* Get the list of nodes in the hierarchy that emits the event. */
- retval = browseRecursive(server, 2, emitStartNodes,
- totalEmitRefTypesSize, totalEmitRefTypes,
- UA_BROWSEDIRECTION_INVERSE, true,
+ retval = browseRecursive(server, 2, emitStartNodes, UA_BROWSEDIRECTION_INVERSE,
+ &emitRefTypes, UA_NODECLASS_UNSPECIFIED, true,
&emitNodesSize, &emitNodes);
if(retval != UA_STATUSCODE_GOOD) {
UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
@@ -55403,74 +60621,37 @@ UA_Server_triggerEvent(UA_Server *server, const UA_NodeId eventNodeId,
/* Add the event to the listening MonitoredItems at each relevant node */
for(size_t i = 0; i < emitNodesSize; i++) {
- const UA_ObjectNode *node = (const UA_ObjectNode*)
- UA_NODESTORE_GET(server, &emitNodes[i].nodeId);
+ /* Get the node */
+ const UA_Node *node = UA_NODESTORE_GET(server, &emitNodes[i].nodeId);
if(!node)
continue;
- if(node->nodeClass != UA_NODECLASS_OBJECT) {
- UA_NODESTORE_RELEASE(server, (const UA_Node*)node);
+
+ /* Only consider objects */
+ if(node->head.nodeClass != UA_NODECLASS_OBJECT) {
+ UA_NODESTORE_RELEASE(server, node);
continue;
}
- for(UA_MonitoredItem *mi = node->monitoredItemQueue; mi != NULL; mi = mi->next) {
- retval = UA_Event_addEventToMonitoredItem(server, &eventNodeId, mi);
+
+ /* Add event to monitoreditems */
+ for(UA_MonitoredItem *mon = node->head.monitoredItems; mon != NULL; mon = mon->next) {
+ /* Is this an Event-MonitoredItem? */
+ if(mon->itemToMonitor.attributeId != UA_ATTRIBUTEID_EVENTNOTIFIER)
+ continue;
+ retval = UA_Event_addEventToMonitoredItem(server, &eventNodeId, mon);
if(retval != UA_STATUSCODE_GOOD) {
UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
- "Events: Could not add the event to a listening node with StatusCode %s",
- UA_StatusCode_name(retval));
+ "Events: Could not add the event to a listening "
+ "node with StatusCode %s", UA_StatusCode_name(retval));
retval = UA_STATUSCODE_GOOD; /* Only log problems with individual emit nodes */
}
}
- UA_NODESTORE_RELEASE(server, (const UA_Node*)node);
+
+ UA_NODESTORE_RELEASE(server, node);
+
+ /* Add event entry in the historical database */
#ifdef UA_ENABLE_HISTORIZING
- if(!server->config.historyDatabase.setEvent)
- continue;
- UA_EventFilter *filter = NULL;
- UA_EventFieldList *fieldList = NULL;
- UA_Variant historicalEventFilterValue;
- UA_Variant_init(&historicalEventFilterValue);
- /* a HistoricalEventNode that has event history available will provide this property */
- retval = readObjectProperty(server, emitNodes[i].nodeId,
- UA_QUALIFIEDNAME(0, "HistoricalEventFilter"),
- &historicalEventFilterValue);
- /* check if the property was found and the read was successful */
- if(retval != UA_STATUSCODE_GOOD) {
- /* do not vex users with no match errors */
- if(retval != UA_STATUSCODE_BADNOMATCH)
- UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
- "Cannot read the HistoricalEventFilter property of a "
- "listening node. StatusCode %s",
- UA_StatusCode_name(retval));
- }
- /* if found then check if HistoricalEventFilter property has a valid value */
- else if(UA_Variant_isEmpty(&historicalEventFilterValue) ||
- !UA_Variant_isScalar(&historicalEventFilterValue) ||
- historicalEventFilterValue.type->typeIndex != UA_TYPES_EVENTFILTER) {
- UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
- "HistoricalEventFilter property of a listening node "
- "does not have a valid value");
- }
- /* finally, if found and valid then filter */
- else {
- filter = (UA_EventFilter*)historicalEventFilterValue.data;
- UA_EventNotification eventNotification;
- retval = UA_Server_filterEvent(server, &server->adminSession, &eventNodeId,
- filter, &eventNotification);
- if(retval == UA_STATUSCODE_GOOD) {
- fieldList = UA_EventFieldList_new();
- *fieldList = eventNotification.fields;
- }
- /* eventNotification structure is not cleared so that users can
- * avoid copying the field list if they want to store it */
- /* EventFilterResult isn't being used currently
- UA_EventFilterResult_clear(&notification->result); */
- }
- server->config.historyDatabase.setEvent(server, server->config.historyDatabase.context,
- &origin, &emitNodes[i].nodeId,
- &eventNodeId, deleteEventNode,
- filter,
- fieldList);
- UA_Variant_clear(&historicalEventFilterValue);
- retval = UA_STATUSCODE_GOOD;
+ if(server->config.historyDatabase.setEvent)
+ setHistoricalEvent(server, &origin, &emitNodes[i].nodeId, &eventNodeId);
#endif
}
@@ -55485,3296 +60666,6147 @@ UA_Server_triggerEvent(UA_Server *server, const UA_NodeId eventNodeId,
}
cleanup:
- for (size_t i=0; i<EMIT_REFS_ROOT_COUNT; i++) {
- UA_Array_delete(emitRefTypes[i], emitRefTypesSize[i], &UA_TYPES[UA_TYPES_NODEID]);
- }
UA_Array_delete(emitNodes, emitNodesSize, &UA_TYPES[UA_TYPES_EXPANDEDNODEID]);
- UA_UNLOCK(server->serviceMutex);
return retval;
}
+UA_StatusCode
+UA_Server_triggerEvent(UA_Server *server, const UA_NodeId eventNodeId,
+ const UA_NodeId origin, UA_ByteString *outEventId,
+ const UA_Boolean deleteEventNode) {
+ UA_LOCK(&server->serviceMutex);
+ UA_StatusCode res =
+ triggerEvent(server, eventNodeId, origin, outEventId, deleteEventNode);
+ UA_UNLOCK(&server->serviceMutex);
+ return res;
+}
#endif /* UA_ENABLE_SUBSCRIPTIONS_EVENTS */
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/plugins/ua_log_stdout.c" ***********************************/
+/**** amalgamated original file "/src/server/ua_subscription_events_filter.c" ****/
-/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
- * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
- * Copyright 2016-2018 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
- * Copyright 2017 (c) Thomas Stalder, Blue Time Concept SA
+ * Copyright 2018 (c) Ari Breitkreuz, fortiss GmbH
+ * Copyright 2020 (c) Christian von Arnim, ISW University of Stuttgart (for VDW and umati)
+ * Copyright 2021 (c) Fraunhofer IOSB (Author: Andreas Ebner)
*/
-#include <stdio.h>
-
-#if UA_MULTITHREADING >= 200
-#include <pthread.h>
-static pthread_mutex_t printf_mutex = PTHREAD_MUTEX_INITIALIZER;
-#endif
+#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
-/* ANSI escape sequences for color output taken from here:
- * https://stackoverflow.com/questions/3219393/stdlib-and-colored-output-in-c*/
+typedef struct {
+ UA_Server *server;
+ UA_Session *session;
+ const UA_NodeId *eventNode;
+ const UA_ContentFilter *contentFilter;
+ UA_ContentFilterResult *contentFilterResult;
+ UA_Variant *valueResult;
+ UA_UInt16 index;
+} UA_FilterOperatorContext;
-#ifdef UA_ENABLE_LOG_COLORS
-# define ANSI_COLOR_RED "\x1b[31m"
-# define ANSI_COLOR_GREEN "\x1b[32m"
-# define ANSI_COLOR_YELLOW "\x1b[33m"
-# define ANSI_COLOR_BLUE "\x1b[34m"
-# define ANSI_COLOR_MAGENTA "\x1b[35m"
-# define ANSI_COLOR_CYAN "\x1b[36m"
-# define ANSI_COLOR_RESET "\x1b[0m"
-#else
-# define ANSI_COLOR_RED ""
-# define ANSI_COLOR_GREEN ""
-# define ANSI_COLOR_YELLOW ""
-# define ANSI_COLOR_BLUE ""
-# define ANSI_COLOR_MAGENTA ""
-# define ANSI_COLOR_CYAN ""
-# define ANSI_COLOR_RESET ""
-#endif
+static UA_StatusCode
+evaluateWhereClauseContentFilter(UA_FilterOperatorContext *ctx);
-const char *logLevelNames[6] = {"trace", "debug",
- ANSI_COLOR_GREEN "info",
- ANSI_COLOR_YELLOW "warn",
- ANSI_COLOR_RED "error",
- ANSI_COLOR_MAGENTA "fatal"};
-const char *logCategoryNames[7] = {"network", "channel", "session", "server",
- "client", "userland", "securitypolicy"};
+/* Resolves a variant of type string or boolean into a corresponding status code */
+static UA_StatusCode
+resolveBoolean(UA_Variant operand) {
+ UA_String value;
+ value = UA_STRING("True");
+ if(((operand.type == &UA_TYPES[UA_TYPES_STRING]) &&
+ (UA_String_equal((UA_String *)operand.data, &value))) ||
+ ((operand.type == &UA_TYPES[UA_TYPES_BOOLEAN]) &&
+ (*(UA_Boolean *)operand.data == UA_TRUE))) {
+ return UA_STATUSCODE_GOOD;
+ }
+ value = UA_STRING("False");
+ if(((operand.type == &UA_TYPES[UA_TYPES_STRING]) &&
+ (UA_String_equal((UA_String *)operand.data, &value))) ||
+ ((operand.type == &UA_TYPES[UA_TYPES_BOOLEAN]) &&
+ (*(UA_Boolean *)operand.data == UA_FALSE))) {
+ return UA_STATUSCODE_BADNOMATCH;
+ }
-#ifdef __clang__
-__attribute__((__format__(__printf__, 4 , 0)))
-#endif
-void
-UA_Log_Stdout_log(void *context, UA_LogLevel level, UA_LogCategory category,
- const char *msg, va_list args) {
+ /* If the operand can't be resolved, an error is returned */
+ return UA_STATUSCODE_BADFILTEROPERANDINVALID;
+}
- /* Assume that context is casted to UA_LogLevel */
- /* TODO we may later change this to a struct with bitfields to filter on category */
- if ( context != NULL && (UA_LogLevel)(uintptr_t)context > level )
- return;
+/* Part 4: 7.4.4.5 SimpleAttributeOperand
+ * The clause can point to any attribute of nodes. Either a child of the event
+ * node and also the event type. */
+static UA_StatusCode
+resolveSimpleAttributeOperand(UA_Server *server, UA_Session *session,
+ const UA_NodeId *origin,
+ const UA_SimpleAttributeOperand *sao,
+ UA_Variant *value) {
+ /* Prepare the ReadValueId */
+ UA_ReadValueId rvi;
+ UA_ReadValueId_init(&rvi);
+ rvi.indexRange = sao->indexRange;
+ rvi.attributeId = sao->attributeId;
- UA_Int64 tOffset = UA_DateTime_localTimeUtcOffset();
- UA_DateTimeStruct dts = UA_DateTime_toStruct(UA_DateTime_now() + tOffset);
+ UA_DataValue v;
-#if UA_MULTITHREADING >= 200
- pthread_mutex_lock(&printf_mutex);
+ if(sao->browsePathSize == 0) {
+ /* If this list (browsePath) is empty, the Node is the instance of the
+ * TypeDefinition. (Part 4, 7.4.4.5) */
+ rvi.nodeId = *origin;
+
+ /* A Condition is an indirection. Look up the target node. */
+ /* TODO: check for Branches! One Condition could have multiple Branches */
+ UA_NodeId conditionTypeId = UA_NODEID_NUMERIC(0, UA_NS0ID_CONDITIONTYPE);
+ if(UA_NodeId_equal(&sao->typeDefinitionId, &conditionTypeId)) {
+#ifdef UA_ENABLE_SUBSCRIPTIONS_ALARMS_CONDITIONS
+ UA_StatusCode res = UA_getConditionId(server, origin, &rvi.nodeId);
+ if(res != UA_STATUSCODE_GOOD)
+ return res;
+#else
+ return UA_STATUSCODE_BADNOTSUPPORTED;
#endif
+ }
- printf("[%04u-%02u-%02u %02u:%02u:%02u.%03u (UTC%+05d)] %s/%s" ANSI_COLOR_RESET "\t",
- dts.year, dts.month, dts.day, dts.hour, dts.min, dts.sec, dts.milliSec,
- (int)(tOffset / UA_DATETIME_SEC / 36), logLevelNames[level], logCategoryNames[category]);
- vprintf(msg, args);
- printf("\n");
- fflush(stdout);
+ v = UA_Server_readWithSession(server, session, &rvi,
+ UA_TIMESTAMPSTORETURN_NEITHER);
+ } else {
+ /* Resolve the browse path, starting from the event-source (and not the
+ * typeDefinitionId). */
+ UA_BrowsePathResult bpr =
+ browseSimplifiedBrowsePath(server, *origin,
+ sao->browsePathSize, sao->browsePath);
+ if(bpr.targetsSize == 0 && bpr.statusCode == UA_STATUSCODE_GOOD)
+ bpr.statusCode = UA_STATUSCODE_BADNOTFOUND;
+ if(bpr.statusCode != UA_STATUSCODE_GOOD) {
+ UA_StatusCode res = bpr.statusCode;
+ UA_BrowsePathResult_clear(&bpr);
+ return res;
+ }
-#if UA_MULTITHREADING >= 200
- pthread_mutex_unlock(&printf_mutex);
-#endif
+ /* Use the first match */
+ rvi.nodeId = bpr.targets[0].targetId.nodeId;
+ v = UA_Server_readWithSession(server, session, &rvi,
+ UA_TIMESTAMPSTORETURN_NEITHER);
+ UA_BrowsePathResult_clear(&bpr);
+ }
+
+ /* Move the result to the output */
+ if(v.status == UA_STATUSCODE_GOOD && v.hasValue)
+ *value = v.value;
+ else
+ UA_Variant_clear(&v.value);
+ return v.status;
}
-void
-UA_Log_Stdout_clear(void *logContext) {
+/* Resolve operands to variants according to the operand type.
+ * Part 4: 7.17.3 Table 142 specifies the allowed types. */
+static UA_Variant
+resolveOperand(UA_FilterOperatorContext *ctx, UA_UInt16 nr) {
+ UA_StatusCode res;
+ UA_Variant variant;
+ UA_Variant_init(&variant);
+ UA_ExtensionObject *op = &ctx->contentFilter->elements[ctx->index].filterOperands[nr];
+ if(op->content.decoded.type == &UA_TYPES[UA_TYPES_SIMPLEATTRIBUTEOPERAND]) {
+ /* SimpleAttributeOperand */
+ res = resolveSimpleAttributeOperand(ctx->server, ctx->session, ctx->eventNode,
+ (UA_SimpleAttributeOperand *)op->content.decoded.data,
+ &variant);
+ } else if(op->content.decoded.type == &UA_TYPES[UA_TYPES_LITERALOPERAND]) {
+ /* LiteralOperand */
+ variant = ((UA_LiteralOperand *)op->content.decoded.data)->value;
+ res = UA_STATUSCODE_GOOD;
+ } else if(op->content.decoded.type == &UA_TYPES[UA_TYPES_ELEMENTOPERAND]) {
+ /* ElementOperand */
+ UA_UInt16 oldIndex = ctx->index;
+ ctx->index = (UA_UInt16)((UA_ElementOperand *)op->content.decoded.data)->index;
+ res = evaluateWhereClauseContentFilter(ctx);
+ variant = ctx->valueResult[ctx->index];
+ ctx->index = oldIndex; /* restore the old index */
+ } else {
+ res = UA_STATUSCODE_BADFILTEROPERANDINVALID;
+ }
+ if(res != UA_STATUSCODE_GOOD && res != UA_STATUSCODE_BADNOMATCH) {
+ variant.type = NULL;
+ ctx->contentFilterResult->elementResults[ctx->index].operandStatusCodes[nr] = res;
+ }
+
+ return variant;
}
-const UA_Logger UA_Log_Stdout_ = {UA_Log_Stdout_log, NULL, UA_Log_Stdout_clear};
-const UA_Logger *UA_Log_Stdout = &UA_Log_Stdout_;
+static UA_StatusCode
+ofTypeOperator(UA_FilterOperatorContext *ctx) {
+ UA_ContentFilterElement *pElement = &ctx->contentFilter->elements[ctx->index];
+ UA_Boolean result = false;
+ ctx->valueResult[ctx->index].type = &UA_TYPES[UA_TYPES_BOOLEAN];
+ if(pElement->filterOperandsSize != 1)
+ return UA_STATUSCODE_BADFILTEROPERANDCOUNTMISMATCH;
+ if(pElement->filterOperands[0].content.decoded.type !=
+ &UA_TYPES[UA_TYPES_LITERALOPERAND])
+ return UA_STATUSCODE_BADFILTEROPERATORUNSUPPORTED;
+
+ UA_LiteralOperand *literalOperand =
+ (UA_LiteralOperand *) pElement->filterOperands[0].content.decoded.data;
+ if(!UA_Variant_isScalar(&literalOperand->value))
+ return UA_STATUSCODE_BADEVENTFILTERINVALID;
-/* By default the client and server is configured with UA_Log_Stdout
- This constructs a logger with a configurable max log level */
+ if(literalOperand->value.type != &UA_TYPES[UA_TYPES_NODEID] || literalOperand->value.data == NULL)
+ return UA_STATUSCODE_BADEVENTFILTERINVALID;
-UA_Logger UA_Log_Stdout_withLevel(UA_LogLevel minlevel)
-{
- UA_Logger logger = {UA_Log_Stdout_log, (void*)minlevel, UA_Log_Stdout_clear};
- return logger;
+ UA_NodeId *literalOperandNodeId = (UA_NodeId *) literalOperand->value.data;
+ UA_Variant typeNodeIdVariant;
+ UA_Variant_init(&typeNodeIdVariant);
+ UA_StatusCode readStatusCode =
+ readObjectProperty(ctx->server, *ctx->eventNode,
+ UA_QUALIFIEDNAME(0, "EventType"), &typeNodeIdVariant);
+ if(readStatusCode != UA_STATUSCODE_GOOD)
+ return readStatusCode;
+
+ if(!UA_Variant_isScalar(&typeNodeIdVariant) ||
+ typeNodeIdVariant.type != &UA_TYPES[UA_TYPES_NODEID] ||
+ typeNodeIdVariant.data == NULL) {
+ UA_LOG_ERROR(&ctx->server->config.logger, UA_LOGCATEGORY_SERVER,
+ "EventType has an invalid type.");
+ UA_Variant_clear(&typeNodeIdVariant);
+ return UA_STATUSCODE_BADINTERNALERROR;
+ }
+ /* check if the eventtype-nodeid is equal to the given oftype argument */
+ result = UA_NodeId_equal((UA_NodeId*) typeNodeIdVariant.data, literalOperandNodeId);
+ /* check if the eventtype-nodeid is a subtype of the given oftype argument */
+ if(!result)
+ result = isNodeInTree_singleRef(ctx->server,
+ (UA_NodeId*) typeNodeIdVariant.data,
+ literalOperandNodeId,
+ UA_REFERENCETYPEINDEX_HASSUBTYPE);
+ UA_Variant_clear(&typeNodeIdVariant);
+ if(!result)
+ return UA_STATUSCODE_BADNOMATCH;
+ return UA_STATUSCODE_GOOD;
}
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/plugins/ua_accesscontrol_default.c" ***********************************/
-
-/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
- * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
- *
- * Copyright 2016-2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
- * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
- * Copyright 2019 (c) HMS Industrial Networks AB (Author: Jonas Green)
- */
+static UA_StatusCode
+andOperator(UA_FilterOperatorContext *ctx) {
+ UA_StatusCode firstBoolean_and = resolveBoolean(resolveOperand(ctx, 0));
+ if(firstBoolean_and == UA_STATUSCODE_BADNOMATCH) {
+ ctx->valueResult[ctx->index].type = &UA_TYPES[UA_TYPES_BOOLEAN];
+ return UA_STATUSCODE_BADNOMATCH;
+ }
+ /* Evaluation of second operand */
+ UA_StatusCode secondBoolean = resolveBoolean(resolveOperand(ctx, 1));
+ /* Filteroperator AND */
+ if(secondBoolean == UA_STATUSCODE_BADNOMATCH) {
+ ctx->valueResult[ctx->index].type = &UA_TYPES[UA_TYPES_BOOLEAN];
+ return UA_STATUSCODE_BADNOMATCH;
+ }
+ if((firstBoolean_and == UA_STATUSCODE_GOOD) &&
+ (secondBoolean == UA_STATUSCODE_GOOD)) {
+ ctx->valueResult[ctx->index].type = &UA_TYPES[UA_TYPES_BOOLEAN];
+ return UA_STATUSCODE_GOOD;
+ }
+ return UA_STATUSCODE_BADFILTERELEMENTINVALID;
+}
+static UA_StatusCode
+orOperator(UA_FilterOperatorContext *ctx) {
+ UA_StatusCode firstBoolean_or = resolveBoolean(resolveOperand(ctx, 0));
+ if(firstBoolean_or == UA_STATUSCODE_GOOD) {
+ ctx->valueResult[ctx->index].type = &UA_TYPES[UA_TYPES_BOOLEAN];
+ return UA_STATUSCODE_GOOD;
+ }
+ /* Evaluation of second operand */
+ UA_StatusCode secondBoolean = resolveBoolean(resolveOperand(ctx, 1));
+ if(secondBoolean == UA_STATUSCODE_GOOD) {
+ ctx->valueResult[ctx->index].type = &UA_TYPES[UA_TYPES_BOOLEAN];
+ return UA_STATUSCODE_GOOD;
+ }
+ if((firstBoolean_or == UA_STATUSCODE_BADNOMATCH) &&
+ (secondBoolean == UA_STATUSCODE_BADNOMATCH)) {
+ ctx->valueResult[ctx->index].type = &UA_TYPES[UA_TYPES_BOOLEAN];
+ return UA_STATUSCODE_BADNOMATCH;
+ }
+ return UA_STATUSCODE_BADFILTERELEMENTINVALID;
+}
-/* Example access control management. Anonymous and username / password login.
- * The access rights are maximally permissive. */
+static UA_Boolean
+isNumericUnsigned(UA_UInt32 dataTypeKind){
+ if(dataTypeKind == UA_DATATYPEKIND_UINT64 ||
+ dataTypeKind == UA_DATATYPEKIND_UINT32 ||
+ dataTypeKind == UA_DATATYPEKIND_UINT16 ||
+ dataTypeKind == UA_DATATYPEKIND_BYTE)
+ return true;
+ return false;
+}
-typedef struct {
- UA_Boolean allowAnonymous;
- size_t usernamePasswordLoginSize;
- UA_UsernamePasswordLogin *usernamePasswordLogin;
-} AccessControlContext;
+static UA_Boolean
+isNumericSigned(UA_UInt32 dataTypeKind){
+ if(dataTypeKind == UA_DATATYPEKIND_INT64 ||
+ dataTypeKind == UA_DATATYPEKIND_INT32 ||
+ dataTypeKind == UA_DATATYPEKIND_INT16 ||
+ dataTypeKind == UA_DATATYPEKIND_SBYTE)
+ return true;
+ return false;
+}
-#define ANONYMOUS_POLICY "open62541-anonymous-policy"
-#define USERNAME_POLICY "open62541-username-policy"
-const UA_String anonymous_policy = UA_STRING_STATIC(ANONYMOUS_POLICY);
-const UA_String username_policy = UA_STRING_STATIC(USERNAME_POLICY);
+static UA_Boolean
+isFloatingPoint(UA_UInt32 dataTypeKind){
+ if(dataTypeKind == UA_DATATYPEKIND_FLOAT ||
+ dataTypeKind == UA_DATATYPEKIND_DOUBLE)
+ return true;
+ return false;
+}
-/************************/
-/* Access Control Logic */
-/************************/
+static UA_Boolean
+isStringType(UA_UInt32 dataTypeKind){
+ if(dataTypeKind == UA_DATATYPEKIND_STRING ||
+ dataTypeKind == UA_DATATYPEKIND_BYTESTRING)
+ return true;
+ return false;
+}
static UA_StatusCode
-activateSession_default(UA_Server *server, UA_AccessControl *ac,
- const UA_EndpointDescription *endpointDescription,
- const UA_ByteString *secureChannelRemoteCertificate,
- const UA_NodeId *sessionId,
- const UA_ExtensionObject *userIdentityToken,
- void **sessionContext) {
- AccessControlContext *context = (AccessControlContext*)ac->context;
+implicitNumericVariantTransformation(UA_Variant *variant, void *data){
+ if(variant->type == &UA_TYPES[UA_TYPES_UINT64]){
+ *(UA_UInt64 *)data = *(UA_UInt64 *)variant->data;
+ UA_Variant_setScalar(variant, data, &UA_TYPES[UA_TYPES_UINT64]);
+ } else if(variant->type == &UA_TYPES[UA_TYPES_UINT32]){
+ *(UA_UInt64 *)data = *(UA_UInt32 *)variant->data;
+ UA_Variant_setScalar(variant, data, &UA_TYPES[UA_TYPES_UINT64]);
+ } else if(variant->type == &UA_TYPES[UA_TYPES_UINT16]){
+ *(UA_UInt64 *)data = *(UA_UInt16 *)variant->data;
+ UA_Variant_setScalar(variant, data, &UA_TYPES[UA_TYPES_UINT64]);
+ } else if(variant->type == &UA_TYPES[UA_TYPES_BYTE]){
+ *(UA_UInt64 *)data = *(UA_Byte *)variant->data;
+ UA_Variant_setScalar(variant, data, &UA_TYPES[UA_TYPES_UINT64]);
+ } else if(variant->type == &UA_TYPES[UA_TYPES_INT64]){
+ *(UA_Int64 *)data = *(UA_Int64 *)variant->data;
+ UA_Variant_setScalar(variant, data, &UA_TYPES[UA_TYPES_INT64]);
+ } else if(variant->type == &UA_TYPES[UA_TYPES_INT32]){
+ *(UA_Int64 *)data = *(UA_Int32 *)variant->data;
+ UA_Variant_setScalar(variant, data, &UA_TYPES[UA_TYPES_INT64]);
+ } else if(variant->type == &UA_TYPES[UA_TYPES_INT16]){
+ *(UA_Int64 *)data = *(UA_Int16 *)variant->data;
+ UA_Variant_setScalar(variant, data, &UA_TYPES[UA_TYPES_INT64]);
+ } else if(variant->type == &UA_TYPES[UA_TYPES_SBYTE]){
+ *(UA_Int64 *)data = *(UA_SByte *)variant->data;
+ UA_Variant_setScalar(variant, data, &UA_TYPES[UA_TYPES_INT64]);
+ } else if(variant->type == &UA_TYPES[UA_TYPES_DOUBLE]){
+ *(UA_Double *)data = *(UA_Double *)variant->data;
+ UA_Variant_setScalar(variant, data, &UA_TYPES[UA_TYPES_DOUBLE]);
+ } else if(variant->type == &UA_TYPES[UA_TYPES_SBYTE]){
+ *(UA_Double *)data = *(UA_Float *)variant->data;
+ UA_Variant_setScalar(variant, data, &UA_TYPES[UA_TYPES_DOUBLE]);
+ } else {
+ return UA_STATUSCODE_BADTYPEMISMATCH;
+ }
+ return UA_STATUSCODE_GOOD;
+}
- /* The empty token is interpreted as anonymous */
- if(userIdentityToken->encoding == UA_EXTENSIONOBJECT_ENCODED_NOBODY) {
- if(!context->allowAnonymous)
- return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
+static UA_StatusCode
+implicitNumericVariantTransformationUnsingedToSigned(UA_Variant *variant, void *data){
+ if(variant->type == &UA_TYPES[UA_TYPES_UINT64]){
+ if(*(UA_UInt64 *)variant->data > UA_INT64_MAX)
+ return UA_STATUSCODE_BADTYPEMISMATCH;
+ *(UA_Int64 *)data = *(UA_Int64 *)variant->data;
+ UA_Variant_setScalar(variant, data, &UA_TYPES[UA_TYPES_INT64]);
+ } else if(variant->type == &UA_TYPES[UA_TYPES_UINT32]){
+ *(UA_Int64 *)data = *(UA_Int32 *)variant->data;
+ UA_Variant_setScalar(variant, data, &UA_TYPES[UA_TYPES_INT64]);
+ } else if(variant->type == &UA_TYPES[UA_TYPES_UINT16]){
+ *(UA_Int64 *)data = *(UA_Int16 *)variant->data;
+ UA_Variant_setScalar(variant, data, &UA_TYPES[UA_TYPES_INT64]);
+ } else if(variant->type == &UA_TYPES[UA_TYPES_BYTE]){
+ *(UA_Int64 *)data = *(UA_Byte *)variant->data;
+ UA_Variant_setScalar(variant, data, &UA_TYPES[UA_TYPES_INT64]);
+ } else {
+ return UA_STATUSCODE_BADTYPEMISMATCH;
+ }
+ return UA_STATUSCODE_GOOD;
+}
- /* No userdata atm */
- *sessionContext = NULL;
- return UA_STATUSCODE_GOOD;
+static UA_StatusCode
+implicitNumericVariantTransformationSignedToUnSigned(UA_Variant *variant, void *data){
+ if(*(UA_Int64 *)variant->data < 0)
+ return UA_STATUSCODE_BADTYPEMISMATCH;
+ if(variant->type == &UA_TYPES[UA_TYPES_INT64]){
+ *(UA_UInt64 *)data = *(UA_UInt64 *)variant->data;
+ UA_Variant_setScalar(variant, data, &UA_TYPES[UA_TYPES_UINT64]);
+ } else if(variant->type == &UA_TYPES[UA_TYPES_INT32]){
+ *(UA_UInt64 *)data = *(UA_UInt32 *)variant->data;
+ UA_Variant_setScalar(variant, data, &UA_TYPES[UA_TYPES_UINT64]);
+ } else if(variant->type == &UA_TYPES[UA_TYPES_INT16]){
+ *(UA_UInt64 *)data = *(UA_UInt16 *)variant->data;
+ UA_Variant_setScalar(variant, data, &UA_TYPES[UA_TYPES_UINT64]);
+ } else if(variant->type == &UA_TYPES[UA_TYPES_SBYTE]){
+ *(UA_UInt64 *)data = *(UA_Byte *)variant->data;
+ UA_Variant_setScalar(variant, data, &UA_TYPES[UA_TYPES_UINT64]);
+ } else {
+ return UA_STATUSCODE_BADTYPEMISMATCH;
}
+ return UA_STATUSCODE_GOOD;
+}
- /* Could the token be decoded? */
- if(userIdentityToken->encoding < UA_EXTENSIONOBJECT_DECODED)
- return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
+/* 0 -> Same Type, 1 -> Implicit Cast, 2 -> Only explicit Cast, -1 -> cast invalid */
+static UA_SByte convertLookup[21][21] = {
+ { 0, 1,-1,-1, 1,-1, 1,-1, 1, 1, 1,-1, 1,-1, 2,-1,-1, 1, 1, 1,-1},
+ { 2, 0,-1,-1, 1,-1, 1,-1, 1, 1, 1,-1, 1,-1, 2,-1,-1, 1, 1, 1,-1},
+ {-1,-1, 0,-1,-1,-1,-1, 2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
+ {-1,-1,-1, 0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 2,-1,-1,-1,-1,-1,-1},
+ { 2, 2,-1,-1, 0,-1, 2,-1, 2, 2, 2,-1, 2,-1, 2,-1,-1, 2, 2, 2,-1},
+ {-1,-1,-1,-1,-1, 0,-1,-1,-1,-1,-1, 2,-1,-1, 1,-1,-1,-1,-1,-1,-1},
+ { 2, 2,-1,-1, 1,-1, 0,-1, 2, 2, 2,-1, 2,-1, 2,-1,-1, 2, 2, 2,-1},
+ {-1,-1, 2,-1,-1,-1,-1, 0,-1,-1,-1,-1,-1,-1, 2,-1,-1,-1,-1,-1,-1},
+ { 2, 2,-1,-1, 1,-1, 1,-1, 0, 1, 1,-1, 2,-1, 2,-1,-1, 2, 1, 1,-1},
+ { 2, 2,-1,-1, 1,-1, 1,-1, 2, 0, 1,-1, 2, 2, 2,-1,-1, 2, 2, 1,-1},
+ { 2, 2,-1,-1, 1,-1, 1,-1, 2, 2, 0,-1, 2, 2, 2,-1,-1, 2, 2, 2,-1},
+ {-1,-1,-1,-1,-1, 1,-1,-1,-1,-1,-1, 0,-1,-1, 1,-1,-1,-1,-1,-1,-1},
+ { 2, 2,-1,-1, 1,-1, 1,-1, 1, 1, 1,-1, 0,-1, 2,-1,-1, 1, 1, 1,-1},
+ {-1,-1,-1,-1,-1,-1,-1,-1,-1, 1, 1,-1,-1, 0,-1,-1,-1, 2, 1, 1,-1},
+ { 1, 1,-1, 2, 1, 2, 1, 1, 1, 1, 1, 2, 1,-1, 0, 2, 2, 1, 1, 1,-1},
+ {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 1, 0,-1,-1,-1,-1,-1},
+ {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 1, 1, 0,-1,-1,-1,-1},
+ { 2, 2,-1,-1, 1,-1, 1,-1, 1, 1, 1,-1, 2, 1, 2,-1,-1, 0, 1, 1,-1},
+ { 2, 2,-1,-1, 1,-1, 1,-1, 2, 1, 1,-1, 2, 2, 2,-1,-1, 2, 0, 1,-1},
+ { 2, 2,-1,-1, 1,-1, 1,-1, 2, 2, 1,-1, 2, 2, 2,-1,-1, 2, 2, 0,-1},
+ {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 0}
+};
- /* Anonymous login */
- if(userIdentityToken->content.decoded.type == &UA_TYPES[UA_TYPES_ANONYMOUSIDENTITYTOKEN]) {
- if(!context->allowAnonymous)
- return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
+/* This array maps the index of the
+ * standard DataType-Kind order to the
+ * order of the type convertion array */
+static UA_Byte dataTypeKindIndex[30] = {
+ 0, 12, 1, 8, 17,
+ 9, 18, 10, 19, 6,
+ 4, 14, 3, 7, 2,
+ 20, 11, 5, 13, 16,
+ 15, 255,255,255,255,
+ 255,255,255,255,255
+};
- const UA_AnonymousIdentityToken *token = (UA_AnonymousIdentityToken*)
- userIdentityToken->content.decoded.data;
+/* The OPC UA Standard defines in Part 4 several data type casting-rules. (see
+ * 1.04 part 4 Table 122)
+ * Return:
+ * 0 -> same type
+ * 1 -> types can be casted implicit
+ * 2 -> types can only be explicitly casted
+ * -1 -> types can't be casted */
+static UA_SByte
+checkTypeCastingOption(const UA_DataType *cast_target, const UA_DataType *cast_source) {
+ UA_Byte firstOperatorTypeKindIndex = dataTypeKindIndex[cast_target->typeKind];
+ UA_Byte secondOperatorTypeKindIndex = dataTypeKindIndex[cast_source->typeKind];
+ if(firstOperatorTypeKindIndex == UA_BYTE_MAX ||
+ secondOperatorTypeKindIndex == UA_BYTE_MAX)
+ return -1;
- /* Compatibility notice: Siemens OPC Scout v10 provides an empty
- * policyId. This is not compliant. For compatibility, assume that empty
- * policyId == ANONYMOUS_POLICY */
- if(token->policyId.data && !UA_String_equal(&token->policyId, &anonymous_policy))
- return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
+ return convertLookup[firstOperatorTypeKindIndex][secondOperatorTypeKindIndex];
+}
- /* No userdata atm */
- *sessionContext = NULL;
- return UA_STATUSCODE_GOOD;
+/* Compare operation for equal, gt, le, gte, lee
+ * UA_STATUSCODE_GOOD if the comparison was true
+ * UA_STATUSCODE_BADNOMATCH if the comparison was false
+ * UA_STATUSCODE_BADFILTEROPERATORINVALID for invalid operators
+ * UA_STATUSCODE_BADTYPEMISMATCH if one of the operands was not numeric
+ * ToDo Array-Casting
+ */
+static UA_StatusCode
+compareOperation(UA_Variant *firstOperand, UA_Variant *secondOperand, UA_FilterOperator op) {
+ /* get precedence of the operand types */
+ UA_Int16 firstOperand_precedence = UA_DataType_getPrecedence(firstOperand->type);
+ UA_Int16 secondOperand_precedence = UA_DataType_getPrecedence(secondOperand->type);
+ /* if the types are not equal and one of the precedence-ranks is -1, then there is
+ no implicit conversion possible and therefore no compare */
+ if(!UA_NodeId_equal(&firstOperand->type->typeId, &secondOperand->type->typeId) &&
+ (firstOperand_precedence == -1 || secondOperand_precedence == -1)){
+ return UA_STATUSCODE_BADTYPEMISMATCH;
}
+ /* check if the precedence order of the operators is swapped */
+ UA_Variant *firstCompareOperand = firstOperand;
+ UA_Variant *secondCompareOperand = secondOperand;
+ UA_Boolean swapped = false;
+ if (firstOperand_precedence < secondOperand_precedence){
+ firstCompareOperand = secondOperand;
+ secondCompareOperand = firstOperand;
+ swapped = true;
+ }
+ UA_SByte castRule =
+ checkTypeCastingOption(firstCompareOperand->type, secondCompareOperand->type);
- /* Username and password */
- if(userIdentityToken->content.decoded.type == &UA_TYPES[UA_TYPES_USERNAMEIDENTITYTOKEN]) {
- const UA_UserNameIdentityToken *userToken =
- (UA_UserNameIdentityToken*)userIdentityToken->content.decoded.data;
-
- if(!UA_String_equal(&userToken->policyId, &username_policy))
- return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
-
- /* The userToken has been decrypted by the server before forwarding
- * it to the plugin. This information can be used here. */
- /* if(userToken->encryptionAlgorithm.length > 0) {} */
-
- /* Empty username and password */
- if(userToken->userName.length == 0 && userToken->password.length == 0)
- return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
+ if(!(castRule == 0 || castRule == 1)){
+ return UA_STATUSCODE_BADTYPEMISMATCH;
+ }
- /* Try to match username/pw */
- UA_Boolean match = false;
- for(size_t i = 0; i < context->usernamePasswordLoginSize; i++) {
- if(UA_String_equal(&userToken->userName, &context->usernamePasswordLogin[i].username) &&
- UA_String_equal(&userToken->password, &context->usernamePasswordLogin[i].password)) {
- match = true;
- break;
+ /* The operand Data-Types influence the behavior and steps for the comparison.
+ * We need to check the operand types and store a rule which is used to select
+ * the right behavior afterwards. */
+ enum compareHandlingRuleEnum {
+ UA_TYPES_EQUAL_ORDERED,
+ UA_TYPES_EQUAL_UNORDERED,
+ UA_TYPES_DIFFERENT_NUMERIC_UNSIGNED,
+ UA_TYPES_DIFFERENT_NUMERIC_SIGNED,
+ UA_TYPES_DIFFERENT_NUMERIC_FLOATING_POINT,
+ UA_TYPES_DIFFERENT_TEXT,
+ UA_TYPES_DIFFERENT_COMPARE_FORBIDDEN,
+ UA_TYPES_DIFFERENT_COMPARE_EXPLIC,
+ UA_TYPES_DIFFERENT_SIGNEDNESS_CAST_TO_SIGNED,
+ UA_TYPES_DIFFERENT_SIGNEDNESS_CAST_TO_UNSIGNED
+ } compareHandlingRuleEnum;
+
+ if(castRule == 0 &&
+ (UA_DataType_isNumeric(firstOperand->type) ||
+ firstCompareOperand->type->typeKind == (UA_UInt32) UA_DATATYPEKIND_DATETIME ||
+ firstCompareOperand->type->typeKind == (UA_UInt32) UA_DATATYPEKIND_STRING ||
+ firstCompareOperand->type->typeKind == (UA_UInt32) UA_DATATYPEKIND_BYTESTRING)){
+ /* Data-Types with a natural order (allow le, gt, lee, gte) */
+ compareHandlingRuleEnum = UA_TYPES_EQUAL_ORDERED;
+ } else if(castRule == 0){
+ /* Data-Types without a natural order (le, gt, lee, gte are not allowed) */
+ compareHandlingRuleEnum = UA_TYPES_EQUAL_UNORDERED;
+ } else if(castRule == 1 &&
+ isNumericSigned(firstOperand->type->typeKind) &&
+ isNumericSigned(secondOperand->type->typeKind)){
+ compareHandlingRuleEnum = UA_TYPES_DIFFERENT_NUMERIC_SIGNED;
+ } else if(castRule == 1 &&
+ isNumericUnsigned(firstOperand->type->typeKind) &&
+ isNumericUnsigned(secondOperand->type->typeKind)){
+ compareHandlingRuleEnum = UA_TYPES_DIFFERENT_NUMERIC_UNSIGNED;
+ } else if(castRule == 1 &&
+ isFloatingPoint(firstOperand->type->typeKind) &&
+ isFloatingPoint(secondOperand->type->typeKind)){
+ compareHandlingRuleEnum = UA_TYPES_DIFFERENT_NUMERIC_FLOATING_POINT;
+ } else if(castRule == 1 &&
+ isStringType(firstOperand->type->typeKind)&&
+ isStringType(secondOperand->type->typeKind)){
+ compareHandlingRuleEnum = UA_TYPES_DIFFERENT_TEXT;
+ } else if(castRule == 1 &&
+ isNumericSigned(firstOperand->type->typeKind) &&
+ isNumericUnsigned(secondOperand->type->typeKind)){
+ compareHandlingRuleEnum = UA_TYPES_DIFFERENT_SIGNEDNESS_CAST_TO_SIGNED;
+ } else if(castRule == 1 &&
+ isNumericSigned(secondOperand->type->typeKind) &&
+ isNumericUnsigned(firstOperand->type->typeKind)){
+ compareHandlingRuleEnum = UA_TYPES_DIFFERENT_SIGNEDNESS_CAST_TO_UNSIGNED;
+ } else if(castRule == -1 || castRule == 2){
+ compareHandlingRuleEnum = UA_TYPES_DIFFERENT_COMPARE_EXPLIC;
+ } else {
+ compareHandlingRuleEnum = UA_TYPES_DIFFERENT_COMPARE_FORBIDDEN;
+ }
+
+ if(compareHandlingRuleEnum == UA_TYPES_DIFFERENT_COMPARE_FORBIDDEN)
+ return UA_STATUSCODE_BADFILTEROPERATORINVALID;
+
+ if(swapped){
+ firstCompareOperand = secondCompareOperand;
+ secondCompareOperand = firstCompareOperand;
+ }
+
+ if(op == UA_FILTEROPERATOR_EQUALS){
+ UA_Byte variantContent[16];
+ memset(&variantContent, 0, sizeof(UA_Byte) * 16);
+ if(compareHandlingRuleEnum == UA_TYPES_DIFFERENT_NUMERIC_SIGNED ||
+ compareHandlingRuleEnum == UA_TYPES_DIFFERENT_NUMERIC_UNSIGNED ||
+ compareHandlingRuleEnum == UA_TYPES_DIFFERENT_NUMERIC_FLOATING_POINT) {
+ implicitNumericVariantTransformation(firstCompareOperand, variantContent);
+ implicitNumericVariantTransformation(secondCompareOperand, &variantContent[8]);
+ } else if(compareHandlingRuleEnum == UA_TYPES_DIFFERENT_SIGNEDNESS_CAST_TO_SIGNED) {
+ implicitNumericVariantTransformation(firstCompareOperand, variantContent);
+ implicitNumericVariantTransformationUnsingedToSigned(secondCompareOperand, &variantContent[8]);
+ } else if(compareHandlingRuleEnum == UA_TYPES_DIFFERENT_SIGNEDNESS_CAST_TO_UNSIGNED) {
+ implicitNumericVariantTransformation(firstCompareOperand, variantContent);
+ implicitNumericVariantTransformationSignedToUnSigned(secondCompareOperand, &variantContent[8]);
+ } else if(compareHandlingRuleEnum == UA_TYPES_DIFFERENT_TEXT) {
+ firstCompareOperand->type = &UA_TYPES[UA_TYPES_STRING];
+ secondCompareOperand->type = &UA_TYPES[UA_TYPES_STRING];
+ } else if(compareHandlingRuleEnum == UA_TYPES_DIFFERENT_COMPARE_FORBIDDEN ||
+ compareHandlingRuleEnum == UA_TYPES_DIFFERENT_COMPARE_EXPLIC ){
+ return UA_STATUSCODE_BADFILTEROPERATORINVALID;
+ }
+ if(UA_order(firstCompareOperand, secondCompareOperand, &UA_TYPES[UA_TYPES_VARIANT]) == UA_ORDER_EQ) {
+ return UA_STATUSCODE_GOOD;
+ }
+ } else {
+ UA_Byte variantContent[16];
+ memset(&variantContent, 0, sizeof(UA_Byte) * 16);
+ if(compareHandlingRuleEnum == UA_TYPES_DIFFERENT_NUMERIC_SIGNED ||
+ compareHandlingRuleEnum == UA_TYPES_DIFFERENT_NUMERIC_UNSIGNED ||
+ compareHandlingRuleEnum == UA_TYPES_DIFFERENT_NUMERIC_FLOATING_POINT) {
+ implicitNumericVariantTransformation(firstCompareOperand, variantContent);
+ implicitNumericVariantTransformation(secondCompareOperand, &variantContent[8]);
+ } else if(compareHandlingRuleEnum == UA_TYPES_DIFFERENT_SIGNEDNESS_CAST_TO_SIGNED) {
+ implicitNumericVariantTransformation(firstCompareOperand, variantContent);
+ implicitNumericVariantTransformationUnsingedToSigned(secondCompareOperand, &variantContent[8]);
+ } else if(compareHandlingRuleEnum == UA_TYPES_DIFFERENT_SIGNEDNESS_CAST_TO_UNSIGNED) {
+ implicitNumericVariantTransformation(firstCompareOperand, variantContent);
+ implicitNumericVariantTransformationSignedToUnSigned(secondCompareOperand, &variantContent[8]);
+ } else if(compareHandlingRuleEnum == UA_TYPES_DIFFERENT_TEXT) {
+ firstCompareOperand->type = &UA_TYPES[UA_TYPES_STRING];
+ secondCompareOperand->type = &UA_TYPES[UA_TYPES_STRING];
+ } else if(compareHandlingRuleEnum == UA_TYPES_EQUAL_UNORDERED) {
+ return UA_STATUSCODE_BADFILTEROPERATORINVALID;
+ } else if(compareHandlingRuleEnum == UA_TYPES_DIFFERENT_COMPARE_FORBIDDEN ||
+ compareHandlingRuleEnum == UA_TYPES_DIFFERENT_COMPARE_EXPLIC) {
+ return UA_STATUSCODE_BADFILTEROPERATORINVALID;
+ }
+ UA_Order gte_result = UA_order(firstCompareOperand, secondCompareOperand,
+ &UA_TYPES[UA_TYPES_VARIANT]);
+ if(op == UA_FILTEROPERATOR_LESSTHAN) {
+ if(gte_result == UA_ORDER_LESS) {
+ return UA_STATUSCODE_GOOD;
+ }
+ } else if(op == UA_FILTEROPERATOR_GREATERTHAN) {
+ if(gte_result == UA_ORDER_MORE) {
+ return UA_STATUSCODE_GOOD;
+ }
+ } else if(op == UA_FILTEROPERATOR_LESSTHANOREQUAL) {
+ if(gte_result == UA_ORDER_LESS || gte_result == UA_ORDER_EQ) {
+ return UA_STATUSCODE_GOOD;
+ }
+ } else if(op == UA_FILTEROPERATOR_GREATERTHANOREQUAL) {
+ if(gte_result == UA_ORDER_MORE || gte_result == UA_ORDER_EQ) {
+ return UA_STATUSCODE_GOOD;
}
}
- if(!match)
- return UA_STATUSCODE_BADUSERACCESSDENIED;
-
- /* No userdata atm */
- *sessionContext = NULL;
- return UA_STATUSCODE_GOOD;
}
-
- /* Unsupported token type */
- return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
+ return UA_STATUSCODE_BADNOMATCH;
}
-static void
-closeSession_default(UA_Server *server, UA_AccessControl *ac,
- const UA_NodeId *sessionId, void *sessionContext) {
- /* no context to clean up */
+static UA_StatusCode
+compareOperator(UA_FilterOperatorContext *ctx) {
+ ctx->valueResult[ctx->index].type = &UA_TYPES[UA_TYPES_BOOLEAN];
+ UA_Variant firstOperand = resolveOperand(ctx, 0);
+ if(UA_Variant_isEmpty(&firstOperand))
+ return UA_STATUSCODE_BADFILTEROPERANDINVALID;
+ UA_Variant secondOperand = resolveOperand(ctx, 1);
+ if(UA_Variant_isEmpty(&secondOperand)) {
+ return UA_STATUSCODE_BADFILTEROPERANDINVALID;
+ }
+ /* ToDo remove the following restriction: Add support for arrays */
+ if(!UA_Variant_isScalar(&firstOperand) || !UA_Variant_isScalar(&secondOperand)){
+ return UA_STATUSCODE_BADFILTEROPERATORUNSUPPORTED;
+ }
+ return compareOperation(&firstOperand, &secondOperand,
+ ctx->contentFilter->elements[ctx->index].filterOperator);
}
-static UA_UInt32
-getUserRightsMask_default(UA_Server *server, UA_AccessControl *ac,
- const UA_NodeId *sessionId, void *sessionContext,
- const UA_NodeId *nodeId, void *nodeContext) {
- return 0xFFFFFFFF;
+static UA_StatusCode
+bitwiseOperator(UA_FilterOperatorContext *ctx) {
+ /* The bitwise operators all have 2 operands which are evaluated equally. */
+ UA_Variant firstOperand = resolveOperand(ctx, 0);
+ if(UA_Variant_isEmpty(&firstOperand)) {
+ return UA_STATUSCODE_BADFILTEROPERANDINVALID;
+ }
+ UA_Variant secondOperand = resolveOperand(ctx, 1);
+ if(UA_Variant_isEmpty(&secondOperand)) {
+ return UA_STATUSCODE_BADFILTEROPERANDINVALID;
+ }
+
+ UA_Boolean bitwiseAnd =
+ ctx->contentFilter->elements[ctx->index].filterOperator == UA_FILTEROPERATOR_BITWISEAND;
+
+ /* check if the operators are integers */
+ if(!UA_DataType_isNumeric(firstOperand.type) ||
+ !UA_DataType_isNumeric(secondOperand.type) ||
+ !UA_Variant_isScalar(&firstOperand) ||
+ !UA_Variant_isScalar(&secondOperand) ||
+ (firstOperand.type == &UA_TYPES[UA_TYPES_DOUBLE]) ||
+ (secondOperand.type == &UA_TYPES[UA_TYPES_DOUBLE]) ||
+ (secondOperand.type == &UA_TYPES[UA_TYPES_FLOAT]) ||
+ (firstOperand.type == &UA_TYPES[UA_TYPES_FLOAT])) {
+ return UA_STATUSCODE_BADFILTEROPERANDINVALID;
+ }
+
+ /* check which is the return type (higher precedence == bigger integer)*/
+ UA_Int16 precedence = UA_DataType_getPrecedence(firstOperand.type);
+ if(precedence > UA_DataType_getPrecedence(secondOperand.type)) {
+ precedence = UA_DataType_getPrecedence(secondOperand.type);
+ }
+
+ switch(precedence){
+ case 3:
+ ctx->valueResult[ctx->index].type = &UA_TYPES[UA_TYPES_INT64];
+ UA_Int64 result_int64;
+ if(bitwiseAnd) {
+ result_int64 = *((UA_Int64 *)firstOperand.data) & *((UA_Int64 *)secondOperand.data);
+ } else {
+ result_int64 = *((UA_Int64 *)firstOperand.data) | *((UA_Int64 *)secondOperand.data);
+ }
+ UA_Int64_copy(&result_int64, (UA_Int64 *) ctx->valueResult[ctx->index].data);
+ break;
+ case 4:
+ ctx->valueResult[ctx->index].type = &UA_TYPES[UA_TYPES_UINT64];
+ UA_UInt64 result_uint64s;
+ if(bitwiseAnd) {
+ result_uint64s = *((UA_UInt64 *)firstOperand.data) & *((UA_UInt64 *)secondOperand.data);
+ } else {
+ result_uint64s = *((UA_UInt64 *)firstOperand.data) | *((UA_UInt64 *)secondOperand.data);
+ }
+ UA_UInt64_copy(&result_uint64s, (UA_UInt64 *) ctx->valueResult[ctx->index].data);
+ break;
+ case 5:
+ ctx->valueResult[ctx->index].type = &UA_TYPES[UA_TYPES_INT32];
+ UA_Int32 result_int32;
+ if(bitwiseAnd) {
+ result_int32 = *((UA_Int32 *)firstOperand.data) & *((UA_Int32 *)secondOperand.data);
+ } else {
+ result_int32 = *((UA_Int32 *)firstOperand.data) | *((UA_Int32 *)secondOperand.data);
+ }
+ UA_Int32_copy(&result_int32, (UA_Int32 *) ctx->valueResult[ctx->index].data);
+ break;
+ case 6:
+ ctx->valueResult[ctx->index].type = &UA_TYPES[UA_TYPES_UINT32];
+ UA_UInt32 result_uint32;
+ if(bitwiseAnd) {
+ result_uint32 = *((UA_UInt32 *)firstOperand.data) & *((UA_UInt32 *)secondOperand.data);
+ } else {
+ result_uint32 = *((UA_UInt32 *)firstOperand.data) | *((UA_UInt32 *)secondOperand.data);
+ }
+ UA_UInt32_copy(&result_uint32, (UA_UInt32 *) ctx->valueResult[ctx->index].data);
+ break;
+ case 8:
+ ctx->valueResult[ctx->index].type = &UA_TYPES[UA_TYPES_INT16];
+ UA_Int16 result_int16;
+ if(bitwiseAnd) {
+ result_int16 = *((UA_Int16 *)firstOperand.data) & *((UA_Int16 *)secondOperand.data);
+ } else {
+ result_int16 = *((UA_Int16 *)firstOperand.data) | *((UA_Int16 *)secondOperand.data);
+ }
+ UA_Int16_copy(&result_int16, (UA_Int16 *) ctx->valueResult[ctx->index].data);
+ break;
+ case 9:
+ ctx->valueResult[ctx->index].type = &UA_TYPES[UA_TYPES_UINT16];
+ UA_UInt16 result_uint16;
+ if(bitwiseAnd) {
+ result_uint16 = *((UA_UInt16 *)firstOperand.data) & *((UA_UInt16 *)secondOperand.data);
+ } else {
+ result_uint16 = *((UA_UInt16 *)firstOperand.data) | *((UA_UInt16 *)secondOperand.data);
+ }
+ UA_UInt16_copy(&result_uint16, (UA_UInt16 *) ctx->valueResult[ctx->index].data);
+ break;
+ case 10:
+ ctx->valueResult[ctx->index].type = &UA_TYPES[UA_TYPES_SBYTE];
+ UA_SByte result_sbyte;
+ if(bitwiseAnd) {
+ result_sbyte = *((UA_SByte *)firstOperand.data) & *((UA_SByte *)secondOperand.data);
+ } else {
+ result_sbyte = *((UA_SByte *)firstOperand.data) | *((UA_SByte *)secondOperand.data);
+ }
+ UA_SByte_copy(&result_sbyte, (UA_SByte *) ctx->valueResult[ctx->index].data);
+ break;
+ case 11:
+ ctx->valueResult[ctx->index].type = &UA_TYPES[UA_TYPES_BYTE];
+ UA_Byte result_byte;
+ if(bitwiseAnd) {
+ result_byte = *((UA_Byte *)firstOperand.data) & *((UA_Byte *)secondOperand.data);
+ } else {
+ result_byte = *((UA_Byte *)firstOperand.data) | *((UA_Byte *)secondOperand.data);
+ }
+ UA_Byte_copy(&result_byte, (UA_Byte *) ctx->valueResult[ctx->index].data);
+ break;
+ default:
+ return UA_STATUSCODE_BADFILTEROPERANDINVALID;
+ }
+ return UA_STATUSCODE_GOOD;
}
-static UA_Byte
-getUserAccessLevel_default(UA_Server *server, UA_AccessControl *ac,
- const UA_NodeId *sessionId, void *sessionContext,
- const UA_NodeId *nodeId, void *nodeContext) {
- return 0xFF;
+static UA_StatusCode
+betweenOperator(UA_FilterOperatorContext *ctx) {
+ ctx->valueResult[ctx->index].type = &UA_TYPES[UA_TYPES_BOOLEAN];
+
+ UA_Variant firstOperand = resolveOperand(ctx, 0);
+ UA_Variant secondOperand = resolveOperand(ctx, 1);
+ UA_Variant thirdOperand = resolveOperand(ctx, 2);
+
+ if((UA_Variant_isEmpty(&firstOperand) ||
+ UA_Variant_isEmpty(&secondOperand) ||
+ UA_Variant_isEmpty(&thirdOperand)) ||
+ (!UA_DataType_isNumeric(firstOperand.type) ||
+ !UA_DataType_isNumeric(secondOperand.type) ||
+ !UA_DataType_isNumeric(thirdOperand.type)) ||
+ (!UA_Variant_isScalar(&firstOperand) ||
+ !UA_Variant_isScalar(&secondOperand) ||
+ !UA_Variant_isScalar(&thirdOperand))) {
+ return UA_STATUSCODE_BADFILTEROPERANDINVALID;
+ }
+
+ /* Between can be evaluated through greaterThanOrEqual and lessThanOrEqual */
+ if(compareOperation(&firstOperand, &secondOperand, UA_FILTEROPERATOR_GREATERTHANOREQUAL) == UA_STATUSCODE_GOOD &&
+ compareOperation(&firstOperand, &thirdOperand, UA_FILTEROPERATOR_LESSTHANOREQUAL) == UA_STATUSCODE_GOOD){
+ return UA_STATUSCODE_GOOD;
+ }
+ return UA_STATUSCODE_BADNOMATCH;
}
-static UA_Boolean
-getUserExecutable_default(UA_Server *server, UA_AccessControl *ac,
- const UA_NodeId *sessionId, void *sessionContext,
- const UA_NodeId *methodId, void *methodContext) {
- return true;
-}
+static UA_StatusCode
+inListOperator(UA_FilterOperatorContext *ctx) {
+ ctx->valueResult[ctx->index].type = &UA_TYPES[UA_TYPES_BOOLEAN];
+ UA_Variant firstOperand = resolveOperand(ctx, 0);
-static UA_Boolean
-getUserExecutableOnObject_default(UA_Server *server, UA_AccessControl *ac,
- const UA_NodeId *sessionId, void *sessionContext,
- const UA_NodeId *methodId, void *methodContext,
- const UA_NodeId *objectId, void *objectContext) {
- return true;
-}
+ if(UA_Variant_isEmpty(&firstOperand) ||
+ !UA_Variant_isScalar(&firstOperand)) {
+ return UA_STATUSCODE_BADFILTEROPERATORUNSUPPORTED;
+ }
-static UA_Boolean
-allowAddNode_default(UA_Server *server, UA_AccessControl *ac,
- const UA_NodeId *sessionId, void *sessionContext,
- const UA_AddNodesItem *item) {
- return true;
-}
+ /* Evaluating the list of operands */
+ for(size_t i = 1; i < ctx->contentFilter->elements[ctx->index].filterOperandsSize; i++) {
+ /* Resolving the current operand */
+ UA_Variant currentOperator = resolveOperand(ctx, (UA_UInt16)i);
-static UA_Boolean
-allowAddReference_default(UA_Server *server, UA_AccessControl *ac,
- const UA_NodeId *sessionId, void *sessionContext,
- const UA_AddReferencesItem *item) {
- return true;
+ /* Check if the operand conforms to the operator*/
+ if(UA_Variant_isEmpty(&currentOperator) ||
+ !UA_Variant_isScalar(&currentOperator)) {
+ return UA_STATUSCODE_BADFILTEROPERATORUNSUPPORTED;
+ }
+ if(compareOperation(&firstOperand, &currentOperator, UA_FILTEROPERATOR_EQUALS)) {
+ return UA_STATUSCODE_GOOD;
+ }
+ }
+ return UA_STATUSCODE_BADNOMATCH;
}
-static UA_Boolean
-allowDeleteNode_default(UA_Server *server, UA_AccessControl *ac,
- const UA_NodeId *sessionId, void *sessionContext,
- const UA_DeleteNodesItem *item) {
- return true;
+static UA_StatusCode
+isNullOperator(UA_FilterOperatorContext *ctx) {
+ /* Checking if operand is NULL. This is done by reducing the operand to a
+ * variant and then checking if it is empty. */
+ UA_Variant operand = resolveOperand(ctx, 0);
+ ctx->valueResult[ctx->index].type = &UA_TYPES[UA_TYPES_BOOLEAN];
+ if(!UA_Variant_isEmpty(&operand))
+ return UA_STATUSCODE_BADNOMATCH;
+ return UA_STATUSCODE_GOOD;
}
-static UA_Boolean
-allowDeleteReference_default(UA_Server *server, UA_AccessControl *ac,
- const UA_NodeId *sessionId, void *sessionContext,
- const UA_DeleteReferencesItem *item) {
- return true;
+static UA_StatusCode
+notOperator(UA_FilterOperatorContext *ctx) {
+ /* Inverting the boolean value of the operand. */
+ UA_StatusCode res = resolveBoolean(resolveOperand(ctx, 0));
+ ctx->valueResult[ctx->index].type = &UA_TYPES[UA_TYPES_BOOLEAN];
+ /* invert result */
+ if(res == UA_STATUSCODE_GOOD)
+ return UA_STATUSCODE_BADNOMATCH;
+ return UA_STATUSCODE_GOOD;
}
-static UA_Boolean
-allowBrowseNode_default(UA_Server *server, UA_AccessControl *ac,
- const UA_NodeId *sessionId, void *sessionContext,
- const UA_NodeId *nodeId, void *nodeContext) {
- return true;
+static UA_StatusCode
+evaluateWhereClauseContentFilter(UA_FilterOperatorContext *ctx) {
+ UA_LOCK_ASSERT(&ctx->server->serviceMutex, 1);
+
+ if(ctx->contentFilter->elements == NULL || ctx->contentFilter->elementsSize == 0) {
+ /* Nothing to do.*/
+ return UA_STATUSCODE_GOOD;
+ }
+
+ /* The first element needs to be evaluated, this might be linked to other
+ * elements, which are evaluated in these cases. See 7.4.1 in Part 4. */
+ UA_ContentFilterElement *pElement = &ctx->contentFilter->elements[ctx->index];
+ UA_StatusCode *result = &ctx->contentFilterResult->elementResults[ctx->index].statusCode;
+ switch(pElement->filterOperator) {
+ case UA_FILTEROPERATOR_INVIEW:
+ /* Fallthrough */
+ case UA_FILTEROPERATOR_RELATEDTO:
+ /* Not allowed for event WhereClause according to 7.17.3 in Part 4 */
+ return UA_STATUSCODE_BADEVENTFILTERINVALID;
+ case UA_FILTEROPERATOR_EQUALS:
+ /* Fallthrough */
+ case UA_FILTEROPERATOR_GREATERTHAN:
+ /* Fallthrough */
+ case UA_FILTEROPERATOR_LESSTHAN:
+ /* Fallthrough */
+ case UA_FILTEROPERATOR_GREATERTHANOREQUAL:
+ /* Fallthrough */
+ case UA_FILTEROPERATOR_LESSTHANOREQUAL:
+ *result = compareOperator(ctx);
+ break;
+ case UA_FILTEROPERATOR_LIKE:
+ return UA_STATUSCODE_BADFILTEROPERATORUNSUPPORTED;
+ case UA_FILTEROPERATOR_NOT:
+ *result = notOperator(ctx);
+ break;
+ case UA_FILTEROPERATOR_BETWEEN:
+ *result = betweenOperator(ctx);
+ break;
+ case UA_FILTEROPERATOR_INLIST:
+ /* ToDo currently only numeric types are allowed */
+ *result = inListOperator(ctx);
+ break;
+ case UA_FILTEROPERATOR_ISNULL:
+ *result = isNullOperator(ctx);
+ break;
+ case UA_FILTEROPERATOR_AND:
+ *result = andOperator(ctx);
+ break;
+ case UA_FILTEROPERATOR_OR:
+ *result = orOperator(ctx);
+ break;
+ case UA_FILTEROPERATOR_CAST:
+ return UA_STATUSCODE_BADFILTEROPERATORUNSUPPORTED;
+ case UA_FILTEROPERATOR_BITWISEAND:
+ *result = bitwiseOperator(ctx);
+ break;
+ case UA_FILTEROPERATOR_BITWISEOR:
+ *result = bitwiseOperator(ctx);
+ break;
+ case UA_FILTEROPERATOR_OFTYPE:
+ *result = ofTypeOperator(ctx);
+ break;
+ default:
+ return UA_STATUSCODE_BADFILTEROPERATORINVALID;
+ }
+
+ if(ctx->valueResult[ctx->index].type == &UA_TYPES[UA_TYPES_BOOLEAN]) {
+ UA_Boolean *res = UA_Boolean_new();
+ if(ctx->contentFilterResult->elementResults[ctx->index].statusCode == UA_STATUSCODE_GOOD)
+ *res = true;
+ else
+ *res = false;
+ ctx->valueResult[ctx->index].data = res;
+ }
+ return ctx->contentFilterResult->elementResults[ctx->index].statusCode;
}
-#ifdef UA_ENABLE_HISTORIZING
-static UA_Boolean
-allowHistoryUpdateUpdateData_default(UA_Server *server, UA_AccessControl *ac,
- const UA_NodeId *sessionId, void *sessionContext,
- const UA_NodeId *nodeId,
- UA_PerformUpdateType performInsertReplace,
- const UA_DataValue *value) {
- return true;
+/* Exposes the filters For unit tests */
+UA_StatusCode
+UA_Server_evaluateWhereClauseContentFilter(UA_Server *server, UA_Session *session,
+ const UA_NodeId *eventNode,
+ const UA_ContentFilter *contentFilter,
+ UA_ContentFilterResult *contentFilterResult) {
+ if(contentFilter->elementsSize == 0)
+ return UA_STATUSCODE_GOOD;
+ /* TODO add maximum lenth size to the server config */
+ if(contentFilter->elementsSize > 256)
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+ UA_Variant valueResult[256];
+ for(size_t i = 0; i < contentFilter->elementsSize; ++i) {
+ UA_Variant_init(&valueResult[i]);
+ }
+
+ UA_FilterOperatorContext ctx;
+ ctx.server = server;
+ ctx.session = session;
+ ctx.eventNode = eventNode;
+ ctx.contentFilter = contentFilter;
+ ctx.contentFilterResult = contentFilterResult;
+ ctx.valueResult = valueResult;
+ ctx.index = 0;
+
+ UA_StatusCode res = evaluateWhereClauseContentFilter(&ctx);
+ for(size_t i = 0; i < ctx.contentFilter->elementsSize; i++) {
+ if(!UA_Variant_isEmpty(&ctx.valueResult[i]))
+ UA_Variant_clear(&ctx.valueResult[i]);
+ }
+ return res;
}
static UA_Boolean
-allowHistoryUpdateDeleteRawModified_default(UA_Server *server, UA_AccessControl *ac,
- const UA_NodeId *sessionId, void *sessionContext,
- const UA_NodeId *nodeId,
- UA_DateTime startTimestamp,
- UA_DateTime endTimestamp,
- bool isDeleteModified) {
- return true;
-}
-#endif
+isValidEvent(UA_Server *server, const UA_NodeId *validEventParent,
+ const UA_NodeId *eventId) {
+ /* find the eventType variableNode */
+ UA_QualifiedName findName = UA_QUALIFIEDNAME(0, "EventType");
+ UA_BrowsePathResult bpr = browseSimplifiedBrowsePath(server, *eventId, 1, &findName);
+ if(bpr.statusCode != UA_STATUSCODE_GOOD || bpr.targetsSize < 1) {
+ UA_BrowsePathResult_clear(&bpr);
+ return false;
+ }
-/***************************************/
-/* Create Delete Access Control Plugin */
-/***************************************/
+ /* Get the EventType Property Node */
+ UA_Variant tOutVariant;
+ UA_Variant_init(&tOutVariant);
-static void clear_default(UA_AccessControl *ac) {
- UA_Array_delete((void*)(uintptr_t)ac->userTokenPolicies,
- ac->userTokenPoliciesSize,
- &UA_TYPES[UA_TYPES_USERTOKENPOLICY]);
- ac->userTokenPolicies = NULL;
- ac->userTokenPoliciesSize = 0;
+ /* Read the Value of EventType Property Node (the Value should be a NodeId) */
+ UA_StatusCode retval = readWithReadValue(server, &bpr.targets[0].targetId.nodeId,
+ UA_ATTRIBUTEID_VALUE, &tOutVariant);
+ if(retval != UA_STATUSCODE_GOOD ||
+ !UA_Variant_hasScalarType(&tOutVariant, &UA_TYPES[UA_TYPES_NODEID])) {
+ UA_BrowsePathResult_clear(&bpr);
+ return false;
+ }
- AccessControlContext *context = (AccessControlContext*)ac->context;
+ const UA_NodeId *tEventType = (UA_NodeId*)tOutVariant.data;
- if (context) {
- for(size_t i = 0; i < context->usernamePasswordLoginSize; i++) {
- UA_String_deleteMembers(&context->usernamePasswordLogin[i].username);
- UA_String_deleteMembers(&context->usernamePasswordLogin[i].password);
- }
- if(context->usernamePasswordLoginSize > 0)
- UA_free(context->usernamePasswordLogin);
- UA_free(ac->context);
- ac->context = NULL;
+ /* check whether the EventType is a Subtype of CondtionType
+ * (Part 9 first implementation) */
+ UA_NodeId conditionTypeId = UA_NODEID_NUMERIC(0, UA_NS0ID_CONDITIONTYPE);
+ if(UA_NodeId_equal(validEventParent, &conditionTypeId) &&
+ isNodeInTree_singleRef(server, tEventType, &conditionTypeId,
+ UA_REFERENCETYPEINDEX_HASSUBTYPE)) {
+ UA_BrowsePathResult_clear(&bpr);
+ UA_Variant_clear(&tOutVariant);
+ return true;
}
-}
-UA_StatusCode
-UA_AccessControl_default(UA_ServerConfig *config, UA_Boolean allowAnonymous,
- const UA_ByteString *userTokenPolicyUri,
- size_t usernamePasswordLoginSize,
- const UA_UsernamePasswordLogin *usernamePasswordLogin) {
- UA_AccessControl *ac = &config->accessControl;
- ac->clear = clear_default;
- ac->activateSession = activateSession_default;
- ac->closeSession = closeSession_default;
- ac->getUserRightsMask = getUserRightsMask_default;
- ac->getUserAccessLevel = getUserAccessLevel_default;
- ac->getUserExecutable = getUserExecutable_default;
- ac->getUserExecutableOnObject = getUserExecutableOnObject_default;
- ac->allowAddNode = allowAddNode_default;
- ac->allowAddReference = allowAddReference_default;
- ac->allowBrowseNode = allowBrowseNode_default;
+ /*EventType is not a Subtype of CondtionType
+ *(ConditionId Clause won't be present in Events, which are not Conditions)*/
+ /* check whether Valid Event other than Conditions */
+ UA_NodeId baseEventTypeId = UA_NODEID_NUMERIC(0, UA_NS0ID_BASEEVENTTYPE);
+ UA_Boolean isSubtypeOfBaseEvent =
+ isNodeInTree_singleRef(server, tEventType, &baseEventTypeId,
+ UA_REFERENCETYPEINDEX_HASSUBTYPE);
-#ifdef UA_ENABLE_HISTORIZING
- ac->allowHistoryUpdateUpdateData = allowHistoryUpdateUpdateData_default;
- ac->allowHistoryUpdateDeleteRawModified = allowHistoryUpdateDeleteRawModified_default;
-#endif
+ UA_BrowsePathResult_clear(&bpr);
+ UA_Variant_clear(&tOutVariant);
+ return isSubtypeOfBaseEvent;
+}
- ac->allowDeleteNode = allowDeleteNode_default;
- ac->allowDeleteReference = allowDeleteReference_default;
+UA_StatusCode
+filterEvent(UA_Server *server, UA_Session *session,
+ const UA_NodeId *eventNode, UA_EventFilter *filter,
+ UA_EventFieldList *efl, UA_EventFilterResult *result) {
+ if(filter->selectClausesSize == 0)
+ return UA_STATUSCODE_BADEVENTFILTERINVALID;
- AccessControlContext *context = (AccessControlContext*)
- UA_malloc(sizeof(AccessControlContext));
- if (!context)
+ UA_EventFieldList_init(efl);
+ efl->eventFields = (UA_Variant *)
+ UA_Array_new(filter->selectClausesSize, &UA_TYPES[UA_TYPES_VARIANT]);
+ if(!efl->eventFields)
return UA_STATUSCODE_BADOUTOFMEMORY;
- memset(context, 0, sizeof(AccessControlContext));
- ac->context = context;
+ efl->eventFieldsSize = filter->selectClausesSize;
- /* Allow anonymous? */
- context->allowAnonymous = allowAnonymous;
-
- /* Copy username/password to the access control plugin */
- if(usernamePasswordLoginSize > 0) {
- context->usernamePasswordLogin = (UA_UsernamePasswordLogin*)
- UA_malloc(usernamePasswordLoginSize * sizeof(UA_UsernamePasswordLogin));
- if(!context->usernamePasswordLogin)
+ /* empty event filter result */
+ UA_EventFilterResult_init(result);
+ result->selectClauseResultsSize = filter->selectClausesSize;
+ result->selectClauseResults = (UA_StatusCode *)
+ UA_Array_new(filter->selectClausesSize, &UA_TYPES[UA_TYPES_STATUSCODE]);
+ if(!result->selectClauseResults) {
+ UA_EventFieldList_clear(efl);
+ UA_EventFilterResult_clear(result);
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ }
+ /* prepare content filter result structure */
+ if(filter->whereClause.elementsSize != 0) {
+ result->whereClauseResult.elementResultsSize = filter->whereClause.elementsSize;
+ result->whereClauseResult.elementResults = (UA_ContentFilterElementResult *)
+ UA_Array_new(filter->whereClause.elementsSize,
+ &UA_TYPES[UA_TYPES_CONTENTFILTERELEMENTRESULT]);
+ if(!result->whereClauseResult.elementResults) {
+ UA_EventFieldList_clear(efl);
+ UA_EventFilterResult_clear(result);
return UA_STATUSCODE_BADOUTOFMEMORY;
- context->usernamePasswordLoginSize = usernamePasswordLoginSize;
- for(size_t i = 0; i < usernamePasswordLoginSize; i++) {
- UA_String_copy(&usernamePasswordLogin[i].username, &context->usernamePasswordLogin[i].username);
- UA_String_copy(&usernamePasswordLogin[i].password, &context->usernamePasswordLogin[i].password);
+ }
+ for(size_t i = 0; i < result->whereClauseResult.elementResultsSize; ++i) {
+ result->whereClauseResult.elementResults[i].operandStatusCodesSize =
+ filter->whereClause.elements->filterOperandsSize;
+ result->whereClauseResult.elementResults[i].operandStatusCodes =
+ (UA_StatusCode *)UA_Array_new(
+ filter->whereClause.elements->filterOperandsSize,
+ &UA_TYPES[UA_TYPES_STATUSCODE]);
+ if(!result->whereClauseResult.elementResults[i].operandStatusCodes) {
+ UA_EventFieldList_clear(efl);
+ UA_EventFilterResult_clear(result);
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ }
}
}
- /* Set the allowed policies */
- size_t policies = 0;
- if(allowAnonymous)
- policies++;
- if(usernamePasswordLoginSize > 0)
- policies++;
- ac->userTokenPoliciesSize = 0;
- ac->userTokenPolicies = (UA_UserTokenPolicy *)
- UA_Array_new(policies, &UA_TYPES[UA_TYPES_USERTOKENPOLICY]);
- if(!ac->userTokenPolicies)
- return UA_STATUSCODE_BADOUTOFMEMORY;
- ac->userTokenPoliciesSize = policies;
+ /* Apply the content (where) filter */
+ UA_StatusCode res =
+ UA_Server_evaluateWhereClauseContentFilter(server, session, eventNode,
+ &filter->whereClause, &result->whereClauseResult);
+ if(res != UA_STATUSCODE_GOOD){
+ UA_EventFieldList_clear(efl);
+ UA_EventFilterResult_clear(result);
+ return res;
+ }
- policies = 0;
- if(allowAnonymous) {
- ac->userTokenPolicies[policies].tokenType = UA_USERTOKENTYPE_ANONYMOUS;
- ac->userTokenPolicies[policies].policyId = UA_STRING_ALLOC(ANONYMOUS_POLICY);
- if (!ac->userTokenPolicies[policies].policyId.data)
- return UA_STATUSCODE_BADOUTOFMEMORY;
- policies++;
+ /* Apply the select filter */
+ /* Check if the browsePath is BaseEventType, in which case nothing more
+ * needs to be checked */
+ UA_NodeId baseEventTypeId = UA_NODEID_NUMERIC(0, UA_NS0ID_BASEEVENTTYPE);
+ for(size_t i = 0; i < filter->selectClausesSize; i++) {
+ if(!UA_NodeId_equal(&filter->selectClauses[i].typeDefinitionId, &baseEventTypeId) &&
+ !isValidEvent(server, &filter->selectClauses[i].typeDefinitionId, eventNode)) {
+ UA_Variant_init(&efl->eventFields[i]);
+ /* EventFilterResult currently isn't being used
+ notification->result.selectClauseResults[i] = UA_STATUSCODE_BADTYPEDEFINITIONINVALID; */
+ continue;
+ }
+
+ /* TODO: Put the result into the selectClausResults */
+ resolveSimpleAttributeOperand(server, session, eventNode,
+ &filter->selectClauses[i], &efl->eventFields[i]);
}
- if(usernamePasswordLoginSize > 0) {
- ac->userTokenPolicies[policies].tokenType = UA_USERTOKENTYPE_USERNAME;
- ac->userTokenPolicies[policies].policyId = UA_STRING_ALLOC(USERNAME_POLICY);
- if(!ac->userTokenPolicies[policies].policyId.data)
- return UA_STATUSCODE_BADOUTOFMEMORY;
+ return UA_STATUSCODE_GOOD;
+}
-#if UA_LOGLEVEL <= 400
- const UA_String noneUri = UA_STRING("http://opcfoundation.org/UA/SecurityPolicy#None");
- if(UA_ByteString_equal(userTokenPolicyUri, &noneUri)) {
- UA_LOG_WARNING(&config->logger, UA_LOGCATEGORY_SERVER,
- "Username/Password configured, but no encrypting SecurityPolicy. "
- "This can leak credentials on the network.");
+/*****************************************/
+/* Validation of Filters during Creation */
+/*****************************************/
+
+/* Initial select clause validation. The following checks are currently performed:
+ * - Check if typedefenitionid or browsepath of any clause is NULL
+ * - Check if the eventType is a subtype of BaseEventType
+ * - Check if attributeId is valid
+ * - Check if browsePath contains null
+ * - Check if indexRange is defined and if it is parsable
+ * - Check if attributeId is value */
+void
+UA_Event_staticSelectClauseValidation(UA_Server *server,
+ const UA_EventFilter *eventFilter,
+ UA_StatusCode *result) {
+ /* The selectClause only has to be checked, if the size is not zero */
+ if(eventFilter->selectClausesSize == 0)
+ return;
+ for(size_t i = 0; i < eventFilter->selectClausesSize; ++i) {
+ result[i] = UA_STATUSCODE_GOOD;
+ /* /typedefenitionid or browsepath of any clause is not NULL ? */
+ if(UA_NodeId_isNull(&eventFilter->selectClauses[i].typeDefinitionId)) {
+ result[i] = UA_STATUSCODE_BADTYPEDEFINITIONINVALID;
+ continue;
+ }
+ /*ToDo: Check the following workaround. In UaExpert Event View the selection
+ * of the Server Object set up 7 select filter entries by default. The last
+ * element ist from node 2782 (A&C ConditionType). Since the reduced
+ * information model dos not contain this type, the result has a brows path of
+ * "null" which results in an error. */
+ UA_NodeId ac_conditionType = UA_NODEID_NUMERIC(0, UA_NS0ID_CONDITIONTYPE);
+ if(UA_NodeId_equal(&eventFilter->selectClauses[i].typeDefinitionId, &ac_conditionType)) {
+ continue;
+ }
+ if(&eventFilter->selectClauses[i].browsePath[0] == NULL) {
+ result[i] = UA_STATUSCODE_BADBROWSENAMEINVALID;
+ continue;
+ }
+ /* eventType is a subtype of BaseEventType ? */
+ UA_NodeId baseEventTypeId = UA_NODEID_NUMERIC(0, UA_NS0ID_BASEEVENTTYPE);
+ if(!isNodeInTree_singleRef(
+ server, &eventFilter->selectClauses[i].typeDefinitionId,
+ &baseEventTypeId, UA_REFERENCETYPEINDEX_HASSUBTYPE)) {
+ result[i] = UA_STATUSCODE_BADTYPEDEFINITIONINVALID;
+ continue;
+ }
+ /* attributeId is valid ? */
+ if(!((0 < eventFilter->selectClauses[i].attributeId) &&
+ (eventFilter->selectClauses[i].attributeId < 28))) {
+ result[i] = UA_STATUSCODE_BADATTRIBUTEIDINVALID;
+ continue;
+ }
+ /* browsePath contains null ? */
+ for(size_t j = 0; j < eventFilter->selectClauses[i].browsePathSize; ++j) {
+ if(UA_QualifiedName_isNull(
+ &eventFilter->selectClauses[i].browsePath[j])) {
+ result[i] = UA_STATUSCODE_BADBROWSENAMEINVALID;
+ break;
+ }
+ }
+
+ /* Get the list of Subtypes from current node */
+ UA_ReferenceTypeSet reftypes_interface =
+ UA_REFTYPESET(UA_REFERENCETYPEINDEX_HASSUBTYPE);
+ UA_ExpandedNodeId *chilTypeNodes = NULL;
+ size_t chilTypeNodesSize = 0;
+ UA_StatusCode res;
+ res = browseRecursive(server, 1, &eventFilter->selectClauses[i].typeDefinitionId,
+ UA_BROWSEDIRECTION_FORWARD, &reftypes_interface, UA_NODECLASS_OBJECTTYPE,
+ true, &chilTypeNodesSize, &chilTypeNodes);
+ if(res!=UA_STATUSCODE_GOOD){
+ result[i] = UA_STATUSCODE_BADATTRIBUTEIDINVALID;
+ continue;
+ }
+
+ UA_Boolean subTypeContainField = false;
+ for (size_t j = 0; j < chilTypeNodesSize; ++j) {
+ /* browsPath element is defined in path */
+ UA_BrowsePathResult bpr =
+ browseSimplifiedBrowsePath(server, chilTypeNodes[j].nodeId,
+ eventFilter->selectClauses[i].browsePathSize,
+ eventFilter->selectClauses[i].browsePath);
+
+ if(bpr.statusCode != UA_STATUSCODE_GOOD){
+ UA_BrowsePathResult_clear(&bpr);
+ continue;
+ }
+ subTypeContainField = true;
+ UA_BrowsePathResult_clear(&bpr);
+ }
+ if(!subTypeContainField)
+ result[i] = UA_STATUSCODE_BADNODEIDUNKNOWN;
+
+ UA_Array_delete(chilTypeNodes, chilTypeNodesSize, &UA_TYPES[UA_TYPES_EXPANDEDNODEID]);
+
+ if(result[i] != UA_STATUSCODE_GOOD)
+ continue;
+ /*indexRange is defined ? */
+ if(!UA_String_equal(&eventFilter->selectClauses[i].indexRange,
+ &UA_STRING_NULL)) {
+ /* indexRange is parsable ? */
+ UA_NumericRange numericRange = UA_NUMERICRANGE("");
+ if(UA_NumericRange_parse(&numericRange,
+ eventFilter->selectClauses[i].indexRange) !=
+ UA_STATUSCODE_GOOD) {
+ result[i] = UA_STATUSCODE_BADINDEXRANGEINVALID;
+ continue;
+ }
+ UA_free(numericRange.dimensions);
+ /* attributeId is value ? */
+ if(eventFilter->selectClauses[i].attributeId != UA_ATTRIBUTEID_VALUE) {
+ result[i] = UA_STATUSCODE_BADTYPEMISMATCH;
+ continue;
+ }
+ }
+ }
+}
+
+/* Initial content filter (where clause) check. Current checks:
+ * - Number of operands for each (supported) operator */
+UA_StatusCode
+UA_Event_staticWhereClauseValidation(UA_Server *server,
+ const UA_ContentFilter *filter,
+ UA_ContentFilterResult *result) {
+ UA_ContentFilterResult_init(result);
+ result->elementResultsSize = filter->elementsSize;
+ if(result->elementResultsSize == 0)
+ return UA_STATUSCODE_GOOD;
+ result->elementResults =
+ (UA_ContentFilterElementResult *)UA_Array_new(
+ result->elementResultsSize,
+ &UA_TYPES[UA_TYPES_CONTENTFILTERELEMENTRESULT]);
+ if(!result->elementResults)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ for(size_t i = 0; i < result->elementResultsSize; ++i) {
+ UA_ContentFilterElementResult *er = &result->elementResults[i];
+ UA_ContentFilterElement ef = filter->elements[i];
+ UA_ContentFilterElementResult_init(er);
+ er->operandStatusCodes =
+ (UA_StatusCode *)UA_Array_new(
+ ef.filterOperandsSize,
+ &UA_TYPES[UA_TYPES_STATUSCODE]);
+ er->operandStatusCodesSize = ef.filterOperandsSize;
+
+ switch(ef.filterOperator) {
+ case UA_FILTEROPERATOR_INVIEW:
+ case UA_FILTEROPERATOR_RELATEDTO: {
+ /* Not allowed for event WhereClause according to 7.17.3 in Part 4 */
+ er->statusCode =
+ UA_STATUSCODE_BADEVENTFILTERINVALID;
+ break;
+ }
+ case UA_FILTEROPERATOR_EQUALS:
+ case UA_FILTEROPERATOR_GREATERTHAN:
+ case UA_FILTEROPERATOR_LESSTHAN:
+ case UA_FILTEROPERATOR_GREATERTHANOREQUAL:
+ case UA_FILTEROPERATOR_LESSTHANOREQUAL:
+ case UA_FILTEROPERATOR_LIKE:
+ case UA_FILTEROPERATOR_CAST:
+ case UA_FILTEROPERATOR_BITWISEAND:
+ case UA_FILTEROPERATOR_BITWISEOR: {
+ if(ef.filterOperandsSize != 2) {
+ er->statusCode =
+ UA_STATUSCODE_BADFILTEROPERANDCOUNTMISMATCH;
+ break;
+ }
+ er->statusCode = UA_STATUSCODE_GOOD;
+ break;
+ }
+ case UA_FILTEROPERATOR_AND:
+ case UA_FILTEROPERATOR_OR: {
+ if(ef.filterOperandsSize != 2) {
+ er->statusCode =
+ UA_STATUSCODE_BADFILTEROPERANDCOUNTMISMATCH;
+ break;
+ }
+ for(size_t j = 0; j < 2; ++j) {
+ if(ef.filterOperands[j].content.decoded.type !=
+ &UA_TYPES[UA_TYPES_ELEMENTOPERAND]) {
+ er->operandStatusCodes[j] =
+ UA_STATUSCODE_BADFILTEROPERANDINVALID;
+ er->statusCode =
+ UA_STATUSCODE_BADFILTEROPERANDINVALID;
+ break;
+ }
+ if(((UA_ElementOperand *)ef.filterOperands[j]
+ .content.decoded.data)->index > filter->elementsSize - 1) {
+ er->operandStatusCodes[j] =
+ UA_STATUSCODE_BADINDEXRANGEINVALID;
+ er->statusCode =
+ UA_STATUSCODE_BADINDEXRANGEINVALID;
+ break;
+ }
+ }
+ er->statusCode = UA_STATUSCODE_GOOD;
+ break;
+ }
+ case UA_FILTEROPERATOR_ISNULL:
+ case UA_FILTEROPERATOR_NOT: {
+ if(ef.filterOperandsSize != 1) {
+ er->statusCode =
+ UA_STATUSCODE_BADFILTEROPERANDCOUNTMISMATCH;
+ break;
+ }
+ er->statusCode = UA_STATUSCODE_GOOD;
+ break;
+ }
+ case UA_FILTEROPERATOR_INLIST: {
+ if(ef.filterOperandsSize <= 2) {
+ er->statusCode =
+ UA_STATUSCODE_BADFILTEROPERANDCOUNTMISMATCH;
+ break;
+ }
+ er->statusCode = UA_STATUSCODE_GOOD;
+ break;
+ }
+ case UA_FILTEROPERATOR_BETWEEN: {
+ if(ef.filterOperandsSize != 3) {
+ er->statusCode =
+ UA_STATUSCODE_BADFILTEROPERANDCOUNTMISMATCH;
+ break;
+ }
+ er->statusCode = UA_STATUSCODE_GOOD;
+ break;
+ }
+ case UA_FILTEROPERATOR_OFTYPE: {
+ if(ef.filterOperandsSize != 1) {
+ er->statusCode =
+ UA_STATUSCODE_BADFILTEROPERANDCOUNTMISMATCH;
+ break;
+ }
+ er->operandStatusCodesSize = ef.filterOperandsSize;
+ if(ef.filterOperands[0].content.decoded.type !=
+ &UA_TYPES[UA_TYPES_LITERALOPERAND]) {
+ er->statusCode =
+ UA_STATUSCODE_BADFILTEROPERANDINVALID;
+ break;
+ }
+ UA_LiteralOperand *literalOperand =
+ (UA_LiteralOperand *)ef.filterOperands[0]
+ .content.decoded.data;
+
+ /* Make sure the &pOperand->nodeId is a subtype of BaseEventType */
+ UA_NodeId baseEventTypeId = UA_NODEID_NUMERIC(0, UA_NS0ID_BASEEVENTTYPE);
+ if(!isNodeInTree_singleRef(
+ server, (UA_NodeId *)literalOperand->value.data, &baseEventTypeId,
+ UA_REFERENCETYPEINDEX_HASSUBTYPE)) {
+ er->statusCode =
+ UA_STATUSCODE_BADNODEIDINVALID;
+ break;
+ }
+ er->statusCode = UA_STATUSCODE_GOOD;
+ break;
+ }
+ default:
+ er->statusCode =
+ UA_STATUSCODE_BADFILTEROPERATORUNSUPPORTED;
+ break;
}
-#endif
- return UA_ByteString_copy(userTokenPolicyUri,
- &ac->userTokenPolicies[policies].securityPolicyUri);
}
return UA_STATUSCODE_GOOD;
}
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/plugins/ua_pki_default.c" ***********************************/
+#endif /* UA_ENABLE_SUBSCRIPTIONS_EVENTS */
-/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
- * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
+/**** amalgamated original file "/plugins/crypto/openssl/securitypolicy_openssl_common.h" ****/
+
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Copyright 2020 (c) Wind River Systems, Inc.
+ * Copyright 2020 (c) basysKom GmbH
*
- * Copyright 2018 (c) Mark Giraud, Fraunhofer IOSB
- * Copyright 2019 (c) Kalycito Infotech Private Limited
- * Copyright 2019 (c) Julius Pfrommer, Fraunhofer IOSB
*/
-#ifdef UA_ENABLE_ENCRYPTION_MBEDTLS
-#include <mbedtls/x509.h>
-#include <mbedtls/x509_crt.h>
-#include <mbedtls/error.h>
+
+#if defined(UA_ENABLE_ENCRYPTION_OPENSSL) || defined(UA_ENABLE_ENCRYPTION_LIBRESSL)
+
+#include <openssl/x509.h>
+#include <openssl/evp.h>
+
+_UA_BEGIN_DECLS
+
+void saveDataToFile(const char *fileName, const UA_ByteString *str);
+void UA_Openssl_Init(void);
+
+UA_StatusCode
+UA_copyCertificate(UA_ByteString *dst, const UA_ByteString *src);
+
+UA_StatusCode
+UA_OpenSSL_RSA_PKCS1_V15_SHA256_Verify(const UA_ByteString *msg,
+ X509 *publicKeyX509,
+ const UA_ByteString *signature);
+UA_StatusCode
+UA_Openssl_X509_GetCertificateThumbprint(const UA_ByteString *certficate,
+ UA_ByteString *pThumbprint,
+ bool bThumbPrint);
+UA_StatusCode
+UA_Openssl_RSA_Oaep_Decrypt(UA_ByteString *data,
+ EVP_PKEY *privateKey);
+UA_StatusCode
+UA_Openssl_RSA_OAEP_Encrypt(UA_ByteString *data, /* The data that is encrypted.
+ The encrypted data will overwrite
+ the data that was supplied. */
+ size_t paddingSize, X509 *publicX509);
+
+UA_StatusCode
+UA_Openssl_Random_Key_PSHA256_Derive(const UA_ByteString *secret,
+ const UA_ByteString *seed,
+ UA_ByteString *out);
+
+UA_StatusCode
+UA_Openssl_RSA_Public_GetKeyLength(X509 *publicKeyX509, UA_Int32 *keyLen);
+
+UA_StatusCode
+UA_Openssl_RSA_PKCS1_V15_SHA256_Sign(const UA_ByteString *data,
+ EVP_PKEY *privateKey,
+ UA_ByteString *outSignature);
+
+UA_StatusCode
+UA_OpenSSL_HMAC_SHA256_Verify(const UA_ByteString *message,
+ const UA_ByteString *key,
+ const UA_ByteString *signature);
+
+UA_StatusCode
+UA_OpenSSL_HMAC_SHA256_Sign(const UA_ByteString *message,
+ const UA_ByteString *key,
+ UA_ByteString *signature);
+
+UA_StatusCode
+UA_OpenSSL_AES_256_CBC_Decrypt(const UA_ByteString *iv,
+ const UA_ByteString *key,
+ UA_ByteString *data /* [in/out]*/);
+
+UA_StatusCode
+UA_OpenSSL_AES_256_CBC_Encrypt(const UA_ByteString *iv,
+ const UA_ByteString *key,
+ UA_ByteString *data /* [in/out]*/);
+
+UA_StatusCode
+UA_OpenSSL_X509_compare(const UA_ByteString *cert, const X509 *b);
+
+UA_StatusCode
+UA_Openssl_RSA_Private_GetKeyLength(EVP_PKEY *privateKey,
+ UA_Int32 *keyLen) ;
+
+UA_StatusCode
+UA_OpenSSL_RSA_PKCS1_V15_SHA1_Verify(const UA_ByteString *msg,
+ X509 *publicKeyX509,
+ const UA_ByteString *signature);
+
+UA_StatusCode
+UA_Openssl_RSA_PKCS1_V15_SHA1_Sign(const UA_ByteString *message,
+ EVP_PKEY *privateKey,
+ UA_ByteString *outSignature);
+UA_StatusCode
+UA_Openssl_Random_Key_PSHA1_Derive(const UA_ByteString *secret,
+ const UA_ByteString *seed,
+ UA_ByteString *out);
+UA_StatusCode
+UA_OpenSSL_HMAC_SHA1_Verify(const UA_ByteString *message,
+ const UA_ByteString *key,
+ const UA_ByteString *signature);
+
+UA_StatusCode
+UA_OpenSSL_HMAC_SHA1_Sign(const UA_ByteString *message,
+ const UA_ByteString *key,
+ UA_ByteString *signature);
+
+UA_StatusCode
+UA_Openssl_RSA_PKCS1_V15_Decrypt(UA_ByteString *data,
+ EVP_PKEY *privateKey);
+
+UA_StatusCode
+UA_Openssl_RSA_PKCS1_V15_Encrypt(UA_ByteString *data,
+ size_t paddingSize,
+ X509 *publicX509);
+
+UA_StatusCode
+UA_OpenSSL_AES_128_CBC_Decrypt(const UA_ByteString *iv,
+ const UA_ByteString *key,
+ UA_ByteString *data /* [in/out]*/);
+
+UA_StatusCode
+UA_OpenSSL_AES_128_CBC_Encrypt(const UA_ByteString *iv,
+ const UA_ByteString *key,
+ UA_ByteString *data /* [in/out]*/);
+
+EVP_PKEY *
+UA_OpenSSL_LoadPrivateKey(const UA_ByteString *privateKey);
+
+X509 *
+UA_OpenSSL_LoadCertificate(const UA_ByteString *certificate);
+
+X509 *
+UA_OpenSSL_LoadDerCertificate(const UA_ByteString *certificate);
+
+X509 *
+UA_OpenSSL_LoadPemCertificate(const UA_ByteString *certificate);
+
+UA_StatusCode
+UA_OpenSSL_LoadLocalCertificate(const UA_ByteString *certificate, UA_ByteString *target);
+
+_UA_END_DECLS
+
+#endif /* defined(UA_ENABLE_ENCRYPTION_OPENSSL) || defined(UA_ENABLE_ENCRYPTION_LIBRESSL) */
+
+
+/**** amalgamated original file "/plugins/crypto/openssl/ua_openssl_version_abstraction.h" ****/
+
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Copyright 2021 (c) Christian von Arnim, ISW University of Stuttgart (for VDW and umati)
+ *
+ */
+
+
+#if defined(UA_ENABLE_ENCRYPTION_OPENSSL) || defined(UA_ENABLE_ENCRYPTION_LIBRESSL)
+
+#include <openssl/x509.h>
+
+#if !defined(OPENSSL_VERSION_NUMBER)
+#error "OPENSSL_VERSION_NUMBER is not defined."
#endif
-#define REMOTECERTIFICATETRUSTED 1
-#define ISSUERKNOWN 2
-#define DUALPARENT 3
-#define PARENTFOUND 4
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
+#define X509_STORE_CTX_set0_trusted_stack(STORE_CTX, CTX_SKTRUSTED) X509_STORE_CTX_trusted_stack(STORE_CTX, CTX_SKTRUSTED)
+#endif
-/************/
-/* AllowAll */
-/************/
+#if OPENSSL_VERSION_NUMBER < 0x1010000fL || defined(LIBRESSL_VERSION_NUMBER)
+#define X509_STORE_CTX_get_check_issued(STORE_CTX) STORE_CTX->check_issued
+#endif
-static UA_StatusCode
-verifyCertificateAllowAll(void *verificationContext,
- const UA_ByteString *certificate) {
- return UA_STATUSCODE_GOOD;
+#if OPENSSL_VERSION_NUMBER < 0x1010000fL || defined(LIBRESSL_VERSION_NUMBER)
+#define get_pkey_rsa(evp) ((evp)->pkey.rsa)
+#else
+#define get_pkey_rsa(evp) EVP_PKEY_get0_RSA(evp)
+#endif
+
+#if OPENSSL_VERSION_NUMBER < 0x1010000fL || defined(LIBRESSL_VERSION_NUMBER)
+#define X509_get0_subject_key_id(PX509_CERT) (const ASN1_OCTET_STRING *)X509_get_ext_d2i(PX509_CERT, NID_subject_key_identifier, NULL, NULL);
+#endif
+
+#endif /* defined(UA_ENABLE_ENCRYPTION_OPENSSL) || defined(UA_ENABLE_ENCRYPTION_LIBRESSL) */
+
+/**** amalgamated original file "/plugins/crypto/openssl/securitypolicy_openssl_common.c" ****/
+
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Copyright 2020 (c) Wind River Systems, Inc.
+ * Copyright 2020 (c) basysKom GmbH
+ * Copyright 2022 (c) Wind River Systems, Inc.
+ */
+
+/*
+modification history
+--------------------
+01feb20,lan written
+*/
+
+
+#if defined(UA_ENABLE_ENCRYPTION_OPENSSL) || defined(UA_ENABLE_ENCRYPTION_LIBRESSL)
+
+#include <openssl/rsa.h>
+#include <openssl/evp.h>
+#include <openssl/err.h>
+#include <openssl/sha.h>
+#include <openssl/x509.h>
+#include <openssl/hmac.h>
+#include <openssl/aes.h>
+#include <openssl/pem.h>
+
+
+#define SHA1_DIGEST_LENGTH 20 /* 160 bits */
+#define RSA_DECRYPT_BUFFER_LENGTH 2048 /* bytes */
+
+
+/** P_SHA256 Context */
+typedef struct UA_Openssl_P_SHA256_Ctx_ {
+ size_t seedLen;
+ size_t secretLen;
+ UA_Byte A[32]; /* 32 bytes of SHA256 output */
+ /*
+ char seed[seedLen];
+ char secret[secretLen]; */
+} UA_Openssl_P_SHA256_Ctx;
+
+#define UA_Openssl_P_SHA256_SEED(ctx) ((ctx)->A+32)
+#define UA_Openssl_P_SHA256_SECRET(ctx) ((ctx)->A+32+(ctx)->seedLen)
+
+/** P_SHA1 Context */
+typedef struct UA_Openssl_P_SHA1_Ctx_ {
+ size_t seedLen;
+ size_t secretLen;
+ UA_Byte A[SHA1_DIGEST_LENGTH]; /* 20 bytes of SHA1 output */
+ /*
+ char seed[seedLen];
+ char secret[secretLen]; */
+} UA_Openssl_P_SHA1_Ctx;
+
+#define UA_Openssl_P_SHA1_SEED(ctx) ((ctx)->A + SHA1_DIGEST_LENGTH)
+#define UA_Openssl_P_SHA1_SECRET(ctx) ((ctx)->A + SHA1_DIGEST_LENGTH +(ctx)->seedLen)
+
+void
+UA_Openssl_Init (void) {
+ /* VxWorks7 has initialized the openssl. */
+#ifndef __VXWORKS__
+ static UA_Int16 bInit = 0;
+ if (bInit == 1)
+ return;
+#if defined(OPENSSL_API_COMPAT) && (OPENSSL_API_COMPAT < 0x10100000L)
+ /* only needed, if OpenSSL < V1.1 */
+ OpenSSL_add_all_algorithms ();
+ ERR_load_crypto_strings ();
+#endif
+ bInit = 1;
+#endif
}
-static UA_StatusCode
-verifyApplicationURIAllowAll(void *verificationContext,
- const UA_ByteString *certificate,
- const UA_String *applicationURI) {
+static int UA_OpenSSL_RSA_Key_Size (EVP_PKEY * key){
+#if (OPENSSL_VERSION_NUMBER >= 0x30000000L)
+ return EVP_PKEY_get_size (key);
+#else
+ return RSA_size (get_pkey_rsa(key));
+#endif
+}
+
+/* UA_copyCertificate - allocalte the buffer, copy the certificate and
+ * add a NULL to the end
+ */
+
+UA_StatusCode
+UA_copyCertificate (UA_ByteString * dst,
+ const UA_ByteString * src) {
+ UA_StatusCode retval = UA_ByteString_allocBuffer (dst, src->length + 1);
+ if (retval != UA_STATUSCODE_GOOD)
+ return retval;
+ (void) memcpy (dst->data, src->data, src->length);
+ dst->data[dst->length - 1] = '\0';
+ dst->length--;
+
return UA_STATUSCODE_GOOD;
}
-static void
-clearVerifyAllowAll(UA_CertificateVerification *cv) {
+static UA_StatusCode
+UA_OpenSSL_RSA_Public_Verify (const UA_ByteString * message,
+ const EVP_MD * evpMd,
+ X509 * publicKeyX509,
+ UA_Int16 padding,
+ const UA_ByteString * signature
+ ) {
+ EVP_MD_CTX * mdctx = NULL;
+ int opensslRet;
+ EVP_PKEY_CTX * evpKeyCtx;
+ EVP_PKEY * evpPublicKey = NULL;
+ UA_StatusCode ret;
+ mdctx = EVP_MD_CTX_create ();
+ if (mdctx == NULL) {
+ ret = UA_STATUSCODE_BADOUTOFMEMORY;
+ goto errout;
+ }
+ evpPublicKey = X509_get_pubkey (publicKeyX509);
+ if (evpPublicKey == NULL) {
+ ret = UA_STATUSCODE_BADOUTOFMEMORY;
+ goto errout;
+ }
+
+ opensslRet = EVP_DigestVerifyInit (mdctx, &evpKeyCtx, evpMd, NULL,
+ evpPublicKey);
+ if (opensslRet != 1) {
+ ret = UA_STATUSCODE_BADINTERNALERROR;
+ goto errout;
+ }
+ EVP_PKEY_CTX_set_rsa_padding (evpKeyCtx, padding);
+ opensslRet = EVP_DigestVerifyUpdate (mdctx, message->data, message->length);
+ if (opensslRet != 1) {
+ ret = UA_STATUSCODE_BADINTERNALERROR;
+ goto errout;
+ }
+ opensslRet = EVP_DigestVerifyFinal(mdctx, signature->data, signature->length);
+ if (opensslRet != 1) {
+ ret = UA_STATUSCODE_BADINTERNALERROR;
+ goto errout;
+ }
+
+ ret = UA_STATUSCODE_GOOD;
+errout:
+ if (evpPublicKey != NULL) {
+ EVP_PKEY_free (evpPublicKey);
+ }
+ if (mdctx != NULL) {
+ EVP_MD_CTX_destroy (mdctx);
+ }
+ return ret;
}
-void UA_CertificateVerification_AcceptAll(UA_CertificateVerification *cv) {
- cv->verifyCertificate = verifyCertificateAllowAll;
- cv->verifyApplicationURI = verifyApplicationURIAllowAll;
- cv->clear = clearVerifyAllowAll;
+UA_StatusCode
+UA_OpenSSL_RSA_PKCS1_V15_SHA256_Verify (const UA_ByteString * msg,
+ X509 * publicKeyX509,
+ const UA_ByteString * signature
+ ) {
+ return UA_OpenSSL_RSA_Public_Verify (msg, EVP_sha256(), publicKeyX509,
+ NID_sha256, signature);
}
-#ifdef UA_ENABLE_ENCRYPTION
-/* Find binary substring. Taken and adjusted from
- * http://tungchingkai.blogspot.com/2011/07/binary-strstr.html */
+/* Get certificate thumbprint, and allocate the buffer. */
-static const unsigned char *
-bstrchr(const unsigned char *s, const unsigned char ch, size_t l) {
- /* find first occurrence of c in char s[] for length l*/
- /* handle special case */
- if(l == 0)
- return (NULL);
+UA_StatusCode
+UA_Openssl_X509_GetCertificateThumbprint (const UA_ByteString * certficate,
+ UA_ByteString * pThumbprint,
+ bool bThumbPrint) {
+ if (bThumbPrint) {
+ pThumbprint->length = SHA_DIGEST_LENGTH;
+ UA_StatusCode ret = UA_ByteString_allocBuffer (pThumbprint, pThumbprint->length);
+ if (ret != UA_STATUSCODE_GOOD) {
+ return ret;
+ }
+ }
+ else {
+ if (pThumbprint->length != SHA_DIGEST_LENGTH) {
+ return UA_STATUSCODE_BADINTERNALERROR;
+ }
+ }
+ X509 * x509Certificate = UA_OpenSSL_LoadCertificate(certficate);
- for(; *s != ch; ++s, --l)
- if(l == 0)
- return (NULL);
- return s;
+ if (x509Certificate == NULL) {
+ if (bThumbPrint) {
+ UA_ByteString_clear (pThumbprint);
+ }
+ return UA_STATUSCODE_BADINTERNALERROR;
+ }
+
+ if (X509_digest (x509Certificate, EVP_sha1(), pThumbprint->data, NULL)
+ != 1) {
+ if (bThumbPrint) {
+ UA_ByteString_clear (pThumbprint);
+ }
+ return UA_STATUSCODE_BADINTERNALERROR;
+ }
+ X509_free(x509Certificate);
+
+ return UA_STATUSCODE_GOOD;
}
-const unsigned char *
-UA_Bstrstr(const unsigned char *s1, size_t l1, const unsigned char *s2, size_t l2) {
- /* find first occurrence of s2[] in s1[] for length l1*/
- const unsigned char *ss1 = s1;
- const unsigned char *ss2 = s2;
- /* handle special case */
- if(l1 == 0)
- return (NULL);
- if(l2 == 0)
- return s1;
+static UA_StatusCode
+UA_Openssl_RSA_Private_Decrypt (UA_ByteString * data,
+ EVP_PKEY * privateKey,
+ UA_Int16 padding) {
+ if (data == NULL || privateKey == NULL) {
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+ }
- /* match prefix */
- for (; (s1 = bstrchr(s1, *s2, (uintptr_t)ss1-(uintptr_t)s1+(uintptr_t)l1)) != NULL &&
- (uintptr_t)ss1-(uintptr_t)s1+(uintptr_t)l1 != 0; ++s1) {
+ if (privateKey == NULL) {
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+ }
- /* match rest of prefix */
- const unsigned char *sc1, *sc2;
- for (sc1 = s1, sc2 = s2; ;)
- if (++sc2 >= ss2+l2)
- return s1;
- else if (*++sc1 != *sc2)
- break;
+ size_t keySize = (size_t) UA_OpenSSL_RSA_Key_Size (privateKey);
+ size_t cipherOffset = 0;
+ size_t outOffset = 0;
+ unsigned char buf[RSA_DECRYPT_BUFFER_LENGTH];
+ size_t decryptedBytes;
+ EVP_PKEY_CTX * ctx;
+ int opensslRet;
+
+ ctx = EVP_PKEY_CTX_new (privateKey, NULL);
+ if (ctx == NULL) {
+ return UA_STATUSCODE_BADOUTOFMEMORY;
}
- return NULL;
+ opensslRet = EVP_PKEY_decrypt_init (ctx);
+ if (opensslRet != 1)
+ {
+ EVP_PKEY_CTX_free (ctx);
+ return UA_STATUSCODE_BADINTERNALERROR;
+ }
+ opensslRet = EVP_PKEY_CTX_set_rsa_padding (ctx, padding);
+ if (opensslRet != 1) {
+ EVP_PKEY_CTX_free (ctx);
+ return UA_STATUSCODE_BADINTERNALERROR;
+ }
+
+ while (cipherOffset < data->length) {
+ decryptedBytes = RSA_DECRYPT_BUFFER_LENGTH;
+ opensslRet = EVP_PKEY_decrypt (ctx,
+ buf, /* where to decrypt */
+ &decryptedBytes,
+ data->data + cipherOffset, /* what to decrypt */
+ keySize
+ );
+ if (opensslRet != 1) {
+ EVP_PKEY_CTX_free (ctx);
+ return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
+ }
+ (void) memcpy(data->data + outOffset, buf, decryptedBytes);
+ cipherOffset += (size_t) keySize;
+ outOffset += decryptedBytes;
+ }
+ data->length = outOffset;
+ EVP_PKEY_CTX_free (ctx);
+
+ return UA_STATUSCODE_GOOD;
}
-#endif /* end of UA_ENABLE_ENCRYPTION */
-#ifdef UA_ENABLE_ENCRYPTION_MBEDTLS
+UA_StatusCode
+UA_Openssl_RSA_Oaep_Decrypt (UA_ByteString * data,
+ EVP_PKEY * privateKey) {
+ return UA_Openssl_RSA_Private_Decrypt (data, privateKey,
+ RSA_PKCS1_OAEP_PADDING);
+}
-// mbedTLS expects PEM data to be null terminated
-// The data length parameter must include the null terminator
-static UA_ByteString copyDataFormatAware(const UA_ByteString *data)
-{
- UA_ByteString result;
- UA_ByteString_init(&result);
+static UA_StatusCode
+UA_Openssl_RSA_Public_Encrypt (const UA_ByteString * message,
+ X509 * publicX509,
+ UA_Int16 padding,
+ size_t paddingSize,
+ UA_ByteString * encrypted) {
+ EVP_PKEY_CTX * ctx = NULL;
+ EVP_PKEY * evpPublicKey = NULL;
+ int opensslRet;
+ UA_StatusCode ret;
+ size_t encryptedTextLen = 0;
+ size_t dataPos = 0;
+ size_t encryptedPos = 0;
+ size_t bytesToEncrypt = 0;
+ size_t encryptedBlockSize = 0;
+ size_t keySize = 0;
- if (!data->length)
- return result;
+ evpPublicKey = X509_get_pubkey (publicX509);
+ if (evpPublicKey == NULL) {
+ ret = UA_STATUSCODE_BADOUTOFMEMORY;
+ goto errout;
+ }
+ ctx = EVP_PKEY_CTX_new (evpPublicKey, NULL);
+ if (ctx == NULL) {
+ ret = UA_STATUSCODE_BADOUTOFMEMORY;
+ goto errout;
+ }
+ opensslRet = EVP_PKEY_encrypt_init (ctx);
+ if (opensslRet != 1) {
+ ret = UA_STATUSCODE_BADINTERNALERROR;
+ goto errout;
+ }
+ opensslRet = EVP_PKEY_CTX_set_rsa_padding (ctx, padding);
+ if (opensslRet != 1) {
+ ret = UA_STATUSCODE_BADINTERNALERROR;
+ goto errout;
+ }
- if (data->length && data->data[0] == '-') {
- UA_ByteString_allocBuffer(&result, data->length + 1);
- memcpy(result.data, data->data, data->length);
- result.data[data->length] = '\0';
- } else {
- UA_ByteString_copy(data, &result);
+ /* get the encrypted block size */
+
+ keySize = (size_t) UA_OpenSSL_RSA_Key_Size (evpPublicKey);
+ if (keySize == 0) {
+ ret = UA_STATUSCODE_BADINTERNALERROR;
+ goto errout;
}
- return result;
+ switch (padding) {
+ case RSA_PKCS1_OAEP_PADDING:
+ case RSA_PKCS1_PADDING:
+ if (keySize <= paddingSize) {
+ ret = UA_STATUSCODE_BADINTERNALERROR;
+ goto errout;
+ }
+ encryptedBlockSize = keySize - paddingSize;
+ break;
+ default:
+ ret = UA_STATUSCODE_BADNOTSUPPORTED;
+ goto errout;
+ break;
+ }
+
+ /* encrypt in reverse order so that [data] may alias [encrypted] */
+
+ dataPos = message->length;
+ encryptedPos = ((dataPos - 1) / encryptedBlockSize + 1) * keySize;
+ bytesToEncrypt = (dataPos - 1) % encryptedBlockSize + 1;
+ encryptedTextLen = encryptedPos;
+
+ while (dataPos > 0) {
+ size_t outlen = keySize;
+ encryptedPos -= keySize;
+ dataPos -= bytesToEncrypt;
+ opensslRet = EVP_PKEY_encrypt (ctx, encrypted->data + encryptedPos, &outlen,
+ message->data + dataPos, bytesToEncrypt);
+
+ if (opensslRet != 1) {
+ ret = UA_STATUSCODE_BADINTERNALERROR;
+ goto errout;
+ }
+ bytesToEncrypt = encryptedBlockSize;
+ }
+ encrypted->length = encryptedTextLen;
+
+ ret = UA_STATUSCODE_GOOD;
+errout:
+ if (evpPublicKey != NULL) {
+ EVP_PKEY_free (evpPublicKey);
+ }
+ if (ctx != NULL) {
+ EVP_PKEY_CTX_free (ctx);
+ }
+ return ret;
}
-typedef struct {
- /* If the folders are defined, we use them to reload the certificates during
- * runtime */
- UA_String trustListFolder;
- UA_String issuerListFolder;
- UA_String revocationListFolder;
+UA_StatusCode
+UA_Openssl_RSA_OAEP_Encrypt (UA_ByteString * data,
+ size_t paddingSize,
+ X509 * publicX509) {
+ UA_ByteString message;
+ UA_StatusCode ret;
- mbedtls_x509_crt certificateTrustList;
- mbedtls_x509_crt certificateIssuerList;
- mbedtls_x509_crl certificateRevocationList;
-} CertInfo;
+ ret = UA_ByteString_copy (data, &message);
+ if (ret != UA_STATUSCODE_GOOD) {
+ return ret;
+ }
+ ret = UA_Openssl_RSA_Public_Encrypt (&message, publicX509,
+ RSA_PKCS1_OAEP_PADDING,
+ paddingSize,
+ data);
+ UA_ByteString_clear (&message);
+ return ret;
+}
-#ifdef __linux__ /* Linux only so far */
+static UA_Openssl_P_SHA256_Ctx *
+P_SHA256_Ctx_Create (const UA_ByteString * secret,
+ const UA_ByteString * seed) {
+ size_t size = (UA_Int32)sizeof (UA_Openssl_P_SHA256_Ctx) + secret->length +
+ seed->length;
+ UA_Openssl_P_SHA256_Ctx * ctx = (UA_Openssl_P_SHA256_Ctx *) UA_malloc (size);
+ if (ctx == NULL) {
+ return NULL;
+ }
+ ctx->secretLen = secret->length;
+ ctx->seedLen = seed->length;
+ (void) memcpy (UA_Openssl_P_SHA256_SEED(ctx), seed->data, seed->length);
+ (void) memcpy (UA_Openssl_P_SHA256_SECRET(ctx), secret->data, secret->length);
+ /* A(0) = seed
+ A(n) = HMAC_HASH(secret, A(n-1)) */
-#include <dirent.h>
-#include <limits.h>
+ if (HMAC (EVP_sha256(), secret->data, (int) secret->length, seed->data,
+ seed->length, ctx->A, NULL) == NULL) {
+ UA_free (ctx);
+ return NULL;
+ }
+
+ return ctx;
+}
static UA_StatusCode
-fileNamesFromFolder(const UA_String *folder, size_t *pathsSize, UA_String **paths) {
- char buf[PATH_MAX + 1];
- if(folder->length > PATH_MAX)
- return UA_STATUSCODE_BADINTERNALERROR;
+P_SHA256_Hash_Generate (UA_Openssl_P_SHA256_Ctx * ctx,
+ UA_Byte * pHas
+ ) {
+ /* Calculate P_SHA256(n) = HMAC_SHA256(secret, A(n)+seed) */
+ if (HMAC (EVP_sha256(),UA_Openssl_P_SHA256_SECRET(ctx), (int) ctx->secretLen,
+ ctx->A, sizeof (ctx->A) + ctx->seedLen, pHas, NULL) == NULL) {
+ return UA_STATUSCODE_BADINTERNALERROR;
+ }
- memcpy(buf, folder->data, folder->length);
- buf[folder->length] = 0;
-
- DIR *dir = opendir(buf);
- if(!dir)
- return UA_STATUSCODE_BADINTERNALERROR;
+ /* Calculate A(n) = HMAC_SHA256(secret, A(n-1)) */
+ if (HMAC (EVP_sha256(),UA_Openssl_P_SHA256_SECRET(ctx), (int) ctx->secretLen,
+ ctx->A, sizeof (ctx->A), ctx->A, NULL) == NULL) {
+ return UA_STATUSCODE_BADINTERNALERROR;
+ }
+ return UA_STATUSCODE_GOOD;
+}
- *paths = (UA_String*)UA_Array_new(256, &UA_TYPES[UA_TYPES_STRING]);
- if(*paths == NULL) {
- closedir(dir);
+UA_StatusCode
+UA_Openssl_Random_Key_PSHA256_Derive (const UA_ByteString * secret,
+ const UA_ByteString * seed,
+ UA_ByteString * out) {
+ size_t keyLen = out->length;
+ size_t iter = keyLen/32 + ((keyLen%32)?1:0);
+ size_t bufferLen = iter * 32;
+ size_t i;
+ UA_StatusCode st;
+
+ UA_Byte * pBuffer = (UA_Byte *) UA_malloc (bufferLen);
+ if (pBuffer == NULL) {
return UA_STATUSCODE_BADOUTOFMEMORY;
}
- struct dirent *ent;
- char buf2[PATH_MAX + 1];
- char *res = realpath(buf, buf2);
- if(!res) {
- closedir(dir);
- return UA_STATUSCODE_BADINTERNALERROR;
+ UA_Openssl_P_SHA256_Ctx * ctx = P_SHA256_Ctx_Create (secret, seed);
+ if (ctx == NULL) {
+ UA_free (pBuffer);
+ return UA_STATUSCODE_BADOUTOFMEMORY;
}
- size_t pathlen = strlen(buf2);
- *pathsSize = 0;
- while((ent = readdir (dir)) != NULL && *pathsSize < 256) {
- if(ent->d_type != DT_REG)
- continue;
- buf2[pathlen] = '/';
- buf2[pathlen+1] = 0;
- strcat(buf2, ent->d_name);
- (*paths)[*pathsSize] = UA_STRING_ALLOC(buf2);
- *pathsSize += 1;
+
+ for (i = 0; i < iter; i++) {
+ st = P_SHA256_Hash_Generate (ctx, pBuffer + (i * 32));
+ if (st != UA_STATUSCODE_GOOD) {
+ UA_free (pBuffer);
+ UA_free (ctx);
+ return st;
+ }
}
- closedir(dir);
- if(*pathsSize == 0) {
- UA_free(*paths);
- *paths = NULL;
+ (void) memcpy (out->data, pBuffer, keyLen);
+ UA_free (pBuffer);
+ UA_free (ctx);
+ return UA_STATUSCODE_GOOD;
+}
+
+/* return the key bytes */
+UA_StatusCode
+UA_Openssl_RSA_Public_GetKeyLength (X509 * publicKeyX509,
+ UA_Int32 * keyLen) {
+ EVP_PKEY * evpKey = X509_get_pubkey (publicKeyX509);
+ if (evpKey == NULL) {
+ return UA_STATUSCODE_BADINTERNALERROR;
+ }
+ *keyLen = UA_OpenSSL_RSA_Key_Size (evpKey);
+
+ EVP_PKEY_free (evpKey);
+
+ return UA_STATUSCODE_GOOD;
+}
+
+UA_StatusCode
+UA_Openssl_RSA_Private_GetKeyLength (EVP_PKEY * privateKey,
+ UA_Int32 * keyLen) {
+ if (privateKey == NULL) {
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
}
+ *keyLen = UA_OpenSSL_RSA_Key_Size (privateKey);
+
return UA_STATUSCODE_GOOD;
}
static UA_StatusCode
-reloadCertificates(CertInfo *ci) {
- UA_StatusCode retval = UA_STATUSCODE_GOOD;
- int err = 0;
+UA_Openssl_RSA_Private_Sign (const UA_ByteString * message,
+ EVP_PKEY * privateKey,
+ const EVP_MD * evpMd,
+ UA_Int16 padding,
+ UA_ByteString * outSignature) {
+ EVP_MD_CTX * mdctx = NULL;
+ int opensslRet;
+ EVP_PKEY_CTX * evpKeyCtx;
+ UA_StatusCode ret;
- /* Load the trustlists */
- if(ci->trustListFolder.length > 0) {
- UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "Reloading the trust-list");
- mbedtls_x509_crt_free(&ci->certificateTrustList);
- mbedtls_x509_crt_init(&ci->certificateTrustList);
+ mdctx = EVP_MD_CTX_create ();
+ if (mdctx == NULL) {
+ ret = UA_STATUSCODE_BADOUTOFMEMORY;
+ goto errout;
+ }
- char f[PATH_MAX];
- memcpy(f, ci->trustListFolder.data, ci->trustListFolder.length);
- f[ci->trustListFolder.length] = 0;
- err = mbedtls_x509_crt_parse_path(&ci->certificateTrustList, f);
- if(err == 0) {
- UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
- "Loaded certificate from %s", f);
- } else {
- char errBuff[300];
- mbedtls_strerror(err, errBuff, 300);
- UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
- "Failed to load certificate from %s", f);
- }
+ if (privateKey == NULL) {
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
}
+ opensslRet = EVP_DigestSignInit (mdctx, &evpKeyCtx, evpMd, NULL, privateKey);
+ if (opensslRet != 1) {
+ ret = UA_STATUSCODE_BADINTERNALERROR;
+ goto errout;
+ }
+ EVP_PKEY_CTX_set_rsa_padding (evpKeyCtx, padding);
- /* Load the revocationlists */
- if(ci->revocationListFolder.length > 0) {
- UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "Reloading the revocation-list");
- size_t pathsSize = 0;
- UA_String *paths = NULL;
- retval = fileNamesFromFolder(&ci->revocationListFolder, &pathsSize, &paths);
- if(retval != UA_STATUSCODE_GOOD)
- return retval;
- mbedtls_x509_crl_free(&ci->certificateRevocationList);
- mbedtls_x509_crl_init(&ci->certificateRevocationList);
- for(size_t i = 0; i < pathsSize; i++) {
- char f[PATH_MAX];
- memcpy(f, paths[i].data, paths[i].length);
- f[paths[i].length] = 0;
- err = mbedtls_x509_crl_parse_file(&ci->certificateRevocationList, f);
- if(err == 0) {
- UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
- "Loaded certificate from %.*s",
- (int)paths[i].length, paths[i].data);
- } else {
- UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
- "Failed to load certificate from %.*s",
- (int)paths[i].length, paths[i].data);
- }
- }
- UA_Array_delete(paths, pathsSize, &UA_TYPES[UA_TYPES_STRING]);
- paths = NULL;
- pathsSize = 0;
+ opensslRet = EVP_DigestSignUpdate (mdctx, message->data, message->length);
+ if (opensslRet != 1) {
+ ret = UA_STATUSCODE_BADINTERNALERROR;
+ goto errout;
+ }
+ opensslRet = EVP_DigestSignFinal (mdctx, outSignature->data, &outSignature->length);
+ if (opensslRet != 1) {
+ ret = UA_STATUSCODE_BADINTERNALERROR;
+ goto errout;
}
- /* Load the issuerlists */
- if(ci->issuerListFolder.length > 0) {
- UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "Reloading the issuer-list");
- mbedtls_x509_crt_free(&ci->certificateIssuerList);
- mbedtls_x509_crt_init(&ci->certificateIssuerList);
- char f[PATH_MAX];
- memcpy(f, ci->issuerListFolder.data, ci->issuerListFolder.length);
- f[ci->issuerListFolder.length] = 0;
- err = mbedtls_x509_crt_parse_path(&ci->certificateIssuerList, f);
- if(err == 0) {
- UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
- "Loaded certificate from %s", f);
- } else {
- UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
- "Failed to load certificate from %s", f);
- }
+ ret = UA_STATUSCODE_GOOD;
+errout:
+ if (mdctx != NULL) {
+ EVP_MD_CTX_destroy (mdctx);
}
+ return ret;
+}
- return retval;
+UA_StatusCode
+UA_Openssl_RSA_PKCS1_V15_SHA256_Sign (const UA_ByteString * message,
+ EVP_PKEY * privateKey,
+ UA_ByteString * outSignature) {
+ return UA_Openssl_RSA_Private_Sign (message, privateKey, EVP_sha256(),
+ NID_sha256, outSignature);
}
-#endif
+UA_StatusCode
+UA_OpenSSL_HMAC_SHA256_Verify (const UA_ByteString * message,
+ const UA_ByteString * key,
+ const UA_ByteString * signature
+ ) {
+ unsigned char buf[SHA256_DIGEST_LENGTH] = {0};
+ UA_ByteString mac = {SHA256_DIGEST_LENGTH, buf};
-static UA_StatusCode
-certificateVerification_verify(void *verificationContext,
- const UA_ByteString *certificate) {
- CertInfo *ci = (CertInfo*)verificationContext;
- if(!ci)
+ if (HMAC (EVP_sha256(), key->data, (int) key->length, message->data, message->length,
+ mac.data, (unsigned int *) &mac.length) == NULL) {
return UA_STATUSCODE_BADINTERNALERROR;
-
-#ifdef __linux__ /* Reload certificates if folder paths are specified */
- reloadCertificates(ci);
-#endif
-
- if(ci->trustListFolder.length == 0 &&
- ci->issuerListFolder.length == 0 &&
- ci->revocationListFolder.length == 0 &&
- ci->certificateTrustList.raw.len == 0 &&
- ci->certificateIssuerList.raw.len == 0 &&
- ci->certificateRevocationList.raw.len == 0) {
- UA_LOG_WARNING(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
- "PKI plugin unconfigured. Accepting the certificate.");
+ }
+ if (UA_ByteString_equal (signature, &mac)) {
return UA_STATUSCODE_GOOD;
}
+ else {
+ return UA_STATUSCODE_BADINTERNALERROR;
+ }
+}
- /* Parse the certificate */
- mbedtls_x509_crt remoteCertificate;
+UA_StatusCode
+UA_OpenSSL_HMAC_SHA256_Sign (const UA_ByteString * message,
+ const UA_ByteString * key,
+ UA_ByteString * signature
+ ) {
+ if (HMAC (EVP_sha256(), key->data, (int) key->length, message->data,
+ message->length,
+ signature->data, (unsigned int *) &(signature->length)) == NULL) {
+ return UA_STATUSCODE_BADINTERNALERROR;
+ }
+ return UA_STATUSCODE_GOOD;
+}
- /* Temporary Object to parse the trustList */
- mbedtls_x509_crt *tempCert = NULL;
+static UA_StatusCode
+UA_OpenSSL_Decrypt (const UA_ByteString * iv,
+ const UA_ByteString * key,
+ const EVP_CIPHER * cipherAlg,
+ UA_ByteString * data /* [in/out]*/) {
+ UA_ByteString ivCopy = {0, NULL};
+ UA_ByteString cipherTxt = {0, NULL};
+ EVP_CIPHER_CTX * ctx = NULL;
+ UA_StatusCode ret;
+ int opensslRet;
+ int outLen;
+ int tmpLen;
- /* Temporary Object to parse the revocationList */
- mbedtls_x509_crl *tempCrl = NULL;
+ /* copy the IV because the AES_cbc_encrypt function overwrites it. */
- /* Temporary Object to identify the parent CA when there is no intermediate CA */
- mbedtls_x509_crt *parentCert = NULL;
+ ret = UA_ByteString_copy (iv, &ivCopy);
+ if (ret != UA_STATUSCODE_GOOD) {
+ goto errout;
+ }
- /* Temporary Object to identify the parent CA when there is intermediate CA */
- mbedtls_x509_crt *parentCert_2 = NULL;
+ ret = UA_ByteString_copy (data, &cipherTxt);
+ if (ret != UA_STATUSCODE_GOOD) {
+ goto errout;
+ }
- /* Flag value to identify if the issuer certificate is found */
- int issuerKnown = 0;
+ ctx = EVP_CIPHER_CTX_new ();
+ if (ctx == NULL) {
+ ret = UA_STATUSCODE_BADOUTOFMEMORY;
+ goto errout;
+ }
- /* Flag value to identify if the parent certificate found */
- int parentFound = 0;
+ /* call EVP_* to decrypt */
- mbedtls_x509_crt_init(&remoteCertificate);
- int mbedErr = mbedtls_x509_crt_parse(&remoteCertificate, certificate->data,
- certificate->length);
- if(mbedErr) {
- /* char errBuff[300]; */
- /* mbedtls_strerror(mbedErr, errBuff, 300); */
- /* UA_LOG_WARNING(data->policyContext->securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY, */
- /* "Could not parse the remote certificate with error: %s", errBuff); */
- return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
+ opensslRet = EVP_DecryptInit_ex (ctx, cipherAlg, NULL, key->data, ivCopy.data);
+ if (opensslRet != 1) {
+ ret = UA_STATUSCODE_BADINTERNALERROR;
+ goto errout;
}
+ /* EVP_DecryptFinal() will return an error code if padding is enabled
+ * and the final block is not correctly formatted.
+ */
+ EVP_CIPHER_CTX_set_padding (ctx, 0);
+ opensslRet = EVP_DecryptUpdate (ctx, data->data, &outLen,
+ cipherTxt.data, (int) cipherTxt.length);
+ if (opensslRet != 1) {
+ ret = UA_STATUSCODE_BADINTERNALERROR;
+ goto errout;
+ }
+ opensslRet = EVP_DecryptFinal_ex (ctx, data->data + outLen, &tmpLen);
+ if (opensslRet != 1) {
+ ret = UA_STATUSCODE_BADINTERNALERROR;
+ goto errout;
+ }
+ outLen += tmpLen;
+ data->length = (size_t) outLen;
+ ret = UA_STATUSCODE_GOOD;
- /* Verify */
- mbedtls_x509_crt_profile crtProfile = {
- MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA1) | MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA256),
- 0xFFFFFF, 0x000000, 128 * 8 // in bits
- }; // TODO: remove magic numbers
+errout:
+ UA_ByteString_clear (&ivCopy);
+ UA_ByteString_clear (&cipherTxt);
+ if (ctx != NULL) {
+ EVP_CIPHER_CTX_free(ctx);
+ }
+ return ret;
+}
- uint32_t flags = 0;
- mbedErr = mbedtls_x509_crt_verify_with_profile(&remoteCertificate,
- &ci->certificateTrustList,
- &ci->certificateRevocationList,
- &crtProfile, NULL, &flags, NULL, NULL);
+static UA_StatusCode
+UA_OpenSSL_Encrypt (const UA_ByteString * iv,
+ const UA_ByteString * key,
+ const EVP_CIPHER * cipherAlg,
+ UA_ByteString * data /* [in/out]*/
+ ) {
- /* Flag to check if the remote certificate is trusted or not */
- int TRUSTED = 0;
+ UA_ByteString ivCopy = {0, NULL};
+ UA_ByteString plainTxt = {0, NULL};
+ EVP_CIPHER_CTX * ctx = NULL;
+ UA_StatusCode ret;
+ int opensslRet;
+ int outLen;
+ int tmpLen;
- /* Check if the remoteCertificate is present in the trustList while mbedErr value is not zero */
- if(mbedErr && !(flags & MBEDTLS_X509_BADCERT_EXPIRED) && !(flags & MBEDTLS_X509_BADCERT_FUTURE)) {
- for(tempCert = &ci->certificateTrustList; tempCert != NULL; tempCert = tempCert->next) {
- if(remoteCertificate.raw.len == tempCert->raw.len &&
- memcmp(remoteCertificate.raw.p, tempCert->raw.p, remoteCertificate.raw.len) == 0) {
- TRUSTED = REMOTECERTIFICATETRUSTED;
- break;
- }
- }
+ /* copy the IV because the AES_cbc_encrypt function overwrites it. */
+
+ ret = UA_ByteString_copy (iv, &ivCopy);
+ if (ret != UA_STATUSCODE_GOOD) {
+ goto errout;
}
- /* If the remote certificate is present in the trustList then check if the issuer certificate
- * of remoteCertificate is present in issuerList */
- if(TRUSTED && mbedErr) {
- mbedErr = mbedtls_x509_crt_verify_with_profile(&remoteCertificate,
- &ci->certificateIssuerList,
- &ci->certificateRevocationList,
- &crtProfile, NULL, &flags, NULL, NULL);
+ ret = UA_ByteString_copy (data, &plainTxt);
+ if (ret != UA_STATUSCODE_GOOD) {
+ goto errout;
+ }
- /* Check if the parent certificate has a CRL file available */
- if(!mbedErr) {
- /* Flag value to identify if that there is an intermediate CA present */
- int dualParent = 0;
+ ctx = EVP_CIPHER_CTX_new ();
+ if (ctx == NULL) {
+ ret = UA_STATUSCODE_BADOUTOFMEMORY;
+ goto errout;
+ }
- /* Identify the topmost parent certificate for the remoteCertificate */
- for( parentCert = &ci->certificateIssuerList; parentCert != NULL; parentCert = parentCert->next ) {
- if(memcmp(remoteCertificate.issuer_raw.p, parentCert->subject_raw.p, parentCert->subject_raw.len) == 0) {
- for(parentCert_2 = &ci->certificateTrustList; parentCert_2 != NULL; parentCert_2 = parentCert_2->next) {
- if(memcmp(parentCert->issuer_raw.p, parentCert_2->subject_raw.p, parentCert_2->subject_raw.len) == 0) {
- dualParent = DUALPARENT;
- parentFound = PARENTFOUND;
- break;
- }
+ /* call EVP_* to encrypt */
- }
+ opensslRet = EVP_EncryptInit_ex (ctx, cipherAlg, NULL, key->data, ivCopy.data);
+ if (opensslRet != 1) {
+ ret = UA_STATUSCODE_BADINTERNALERROR;
+ goto errout;
+ }
+ opensslRet = EVP_EncryptUpdate (ctx, data->data, &outLen,
+ plainTxt.data, (int) plainTxt.length);
+ if (opensslRet != 1) {
+ ret = UA_STATUSCODE_BADINTERNALERROR;
+ goto errout;
+ }
+ /*
+ * Buffer passed to EVP_EncryptFinal() must be after data just
+ * encrypted to avoid overwriting it.
+ */
+ opensslRet = EVP_EncryptFinal_ex(ctx, data->data + outLen, &tmpLen);
+ if (opensslRet != 1) {
+ ret = UA_STATUSCODE_BADINTERNALERROR;
+ goto errout;
+ }
+ outLen += tmpLen;
+ data->length = (size_t) outLen;
+ ret = UA_STATUSCODE_GOOD;
- parentFound = PARENTFOUND;
- }
+errout:
+ UA_ByteString_clear (&ivCopy);
+ UA_ByteString_clear (&plainTxt);
+ if (ctx != NULL) {
+ EVP_CIPHER_CTX_free(ctx);
+ }
+ return ret;
+}
- if(parentFound == PARENTFOUND) {
- break;
- }
+UA_StatusCode
+UA_OpenSSL_AES_256_CBC_Decrypt (const UA_ByteString * iv,
+ const UA_ByteString * key,
+ UA_ByteString * data /* [in/out]*/
+ ) {
+ return UA_OpenSSL_Decrypt (iv, key, EVP_aes_256_cbc (), data);
+}
- }
+UA_StatusCode
+UA_OpenSSL_AES_256_CBC_Encrypt (const UA_ByteString * iv,
+ const UA_ByteString * key,
+ UA_ByteString * data /* [in/out]*/
+ ) {
+ return UA_OpenSSL_Encrypt (iv, key, EVP_aes_256_cbc (), data);
+}
- /* Check if there is an intermediate certificate between the topmost parent
- * certificate and child certificate
- * If yes the topmost parent certificate is to be checked whether it has a
- * CRL file avaiable */
- if(dualParent == DUALPARENT && parentFound == PARENTFOUND) {
- parentCert = parentCert_2;
- }
+UA_StatusCode
+UA_OpenSSL_X509_compare (const UA_ByteString * cert,
+ const X509 * bcert) {
+ X509 * acert = UA_OpenSSL_LoadCertificate(cert);
+ if (acert == NULL) {
+ return UA_STATUSCODE_BADCERTIFICATEINVALID;
+ }
+ int opensslRet = X509_cmp (acert, bcert);
+ X509_free (acert);
- /* If a parent certificate is found traverse the revocationList and identify
- * if there is any CRL file that corresponds to the parentCertificate */
- if(parentFound == PARENTFOUND) {
- tempCrl = &ci->certificateRevocationList;
- while(tempCrl != NULL) {
- if(tempCrl->version != 0 &&
- tempCrl->issuer_raw.len == parentCert->subject_raw.len &&
- memcmp(tempCrl->issuer_raw.p,
- parentCert->subject_raw.p,
- tempCrl->issuer_raw.len) == 0) {
- issuerKnown = ISSUERKNOWN;
- break;
- }
+ if (opensslRet == 0)
+ return UA_STATUSCODE_GOOD;
+ return UA_STATUSCODE_UNCERTAINSUBNORMAL;
+}
- tempCrl = tempCrl->next;
- }
+UA_StatusCode
+UA_OpenSSL_RSA_PKCS1_V15_SHA1_Verify (const UA_ByteString * msg,
+ X509 * publicKeyX509,
+ const UA_ByteString * signature) {
+ return UA_OpenSSL_RSA_Public_Verify (msg, EVP_sha1(), publicKeyX509,
+ NID_sha1, signature);
+}
- /* If the CRL file corresponding to the parent certificate is not present
- * then return UA_STATUSCODE_BADCERTIFICATEISSUERREVOCATIONUNKNOWN */
- if(!issuerKnown) {
- return UA_STATUSCODE_BADCERTIFICATEISSUERREVOCATIONUNKNOWN;
- }
+UA_StatusCode
+UA_Openssl_RSA_PKCS1_V15_SHA1_Sign (const UA_ByteString * message,
+ EVP_PKEY * privateKey,
+ UA_ByteString * outSignature) {
+ return UA_Openssl_RSA_Private_Sign (message, privateKey, EVP_sha1(),
+ NID_sha1, outSignature);
+}
- }
+static UA_Openssl_P_SHA1_Ctx *
+P_SHA1_Ctx_Create (const UA_ByteString * secret,
+ const UA_ByteString * seed) {
+ size_t size = (UA_Int32)sizeof (UA_Openssl_P_SHA1_Ctx) + secret->length +
+ seed->length;
+ UA_Openssl_P_SHA1_Ctx * ctx = (UA_Openssl_P_SHA1_Ctx *) UA_malloc (size);
+ if (ctx == NULL) {
+ return NULL;
+ }
- }
+ ctx->secretLen = secret->length;
+ ctx->seedLen = seed->length;
+ (void) memcpy (UA_Openssl_P_SHA1_SEED(ctx), seed->data, seed->length);
+ (void) memcpy (UA_Openssl_P_SHA1_SECRET(ctx), secret->data, secret->length);
+ /* A(0) = seed
+ A(n) = HMAC_HASH(secret, A(n-1)) */
+ if (HMAC (EVP_sha1(), secret->data, (int) secret->length, seed->data,
+ seed->length, ctx->A, NULL) == NULL) {
+ UA_free (ctx);
+ return NULL;
}
- else if(!mbedErr && !TRUSTED) {
- /* This else if section is to identify if the parent certificate which is present in trustList
- * has CRL file corresponding to it */
- /* Identify the parent certificate of the remoteCertificate */
- for(parentCert = &ci->certificateTrustList; parentCert != NULL; parentCert = parentCert->next) {
- if(memcmp(remoteCertificate.issuer_raw.p, parentCert->subject_raw.p, parentCert->subject_raw.len) == 0) {
- parentFound = PARENTFOUND;
- break;
- }
+ return ctx;
+}
+static UA_StatusCode
+P_SHA1_Hash_Generate (UA_Openssl_P_SHA1_Ctx * ctx,
+ UA_Byte * pHas
+ ) {
+ /* Calculate P_SHA1(n) = HMAC_SHA1(secret, A(n)+seed) */
+ if (HMAC (EVP_sha1 (), UA_Openssl_P_SHA1_SECRET(ctx), (int) ctx->secretLen,
+ ctx->A, sizeof (ctx->A) + ctx->seedLen, pHas, NULL) == NULL) {
+ return UA_STATUSCODE_BADINTERNALERROR;
}
- /* If the parent certificate is found traverse the revocationList and identify
- * if there is any CRL file that corresponds to the parentCertificate */
- if(parentFound == PARENTFOUND &&
- memcmp(remoteCertificate.issuer_raw.p, remoteCertificate.subject_raw.p, remoteCertificate.subject_raw.len) != 0) {
- tempCrl = &ci->certificateRevocationList;
- while(tempCrl != NULL) {
- if(tempCrl->version != 0 &&
- tempCrl->issuer_raw.len == parentCert->subject_raw.len &&
- memcmp(tempCrl->issuer_raw.p,
- parentCert->subject_raw.p,
- tempCrl->issuer_raw.len) == 0) {
- issuerKnown = ISSUERKNOWN;
- break;
- }
-
- tempCrl = tempCrl->next;
- }
-
- /* If the CRL file corresponding to the parent certificate is not present
- * then return UA_STATUSCODE_BADCERTIFICATEREVOCATIONUNKNOWN */
- if(!issuerKnown) {
- return UA_STATUSCODE_BADCERTIFICATEREVOCATIONUNKNOWN;
- }
-
+ /* Calculate A(n) = HMAC_SHA1(secret, A(n-1)) */
+ if (HMAC (EVP_sha1(), UA_Openssl_P_SHA1_SECRET(ctx), (int) ctx->secretLen,
+ ctx->A, sizeof (ctx->A), ctx->A, NULL) == NULL) {
+ return UA_STATUSCODE_BADINTERNALERROR;
}
+ return UA_STATUSCODE_GOOD;
+}
+UA_StatusCode
+UA_Openssl_Random_Key_PSHA1_Derive (const UA_ByteString * secret,
+ const UA_ByteString * seed,
+ UA_ByteString * out) {
+ size_t keyLen = out->length;
+ size_t iter = keyLen / SHA1_DIGEST_LENGTH + ((keyLen % SHA1_DIGEST_LENGTH)?1:0);
+ size_t bufferLen = iter * SHA1_DIGEST_LENGTH;
+ UA_Byte * pBuffer = (UA_Byte *) UA_malloc (bufferLen);
+ if (pBuffer == NULL) {
+ return UA_STATUSCODE_BADOUTOFMEMORY;
}
- // TODO: Extend verification
-
- /* This condition will check whether the certificate is a User certificate
- * or a CA certificate. If the MBEDTLS_X509_KU_KEY_CERT_SIGN and
- * MBEDTLS_X509_KU_CRL_SIGN of key_usage are set, then the certificate
- * shall be condidered as CA Certificate and cannot be used to establish a
- * connection. Refer the test case CTT/Security/Security Certificate Validation/029.js
- * for more details */
- if((remoteCertificate.key_usage & MBEDTLS_X509_KU_KEY_CERT_SIGN) &&
- (remoteCertificate.key_usage & MBEDTLS_X509_KU_CRL_SIGN)) {
- return UA_STATUSCODE_BADCERTIFICATEUSENOTALLOWED;
+ UA_Openssl_P_SHA1_Ctx * ctx = P_SHA1_Ctx_Create (secret, seed);
+ if (ctx == NULL) {
+ UA_free (pBuffer);
+ return UA_STATUSCODE_BADOUTOFMEMORY;
}
- UA_StatusCode retval = UA_STATUSCODE_GOOD;
- if(mbedErr) {
-#if UA_LOGLEVEL <= 400
- char buff[100];
- int len = mbedtls_x509_crt_verify_info(buff, 100, "", flags);
- UA_LOG_WARNING(UA_Log_Stdout, UA_LOGCATEGORY_SECURITYPOLICY,
- "Verifying the certificate failed with error: %.*s", len-1, buff);
-#endif
- if(flags & (uint32_t)MBEDTLS_X509_BADCERT_NOT_TRUSTED) {
- retval = UA_STATUSCODE_BADCERTIFICATEUNTRUSTED;
- } else if(flags & (uint32_t)MBEDTLS_X509_BADCERT_FUTURE ||
- flags & (uint32_t)MBEDTLS_X509_BADCERT_EXPIRED) {
- retval = UA_STATUSCODE_BADCERTIFICATETIMEINVALID;
- } else if(flags & (uint32_t)MBEDTLS_X509_BADCERT_REVOKED ||
- flags & (uint32_t)MBEDTLS_X509_BADCRL_EXPIRED) {
- retval = UA_STATUSCODE_BADCERTIFICATEREVOKED;
- } else {
- retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
+ size_t i;
+ UA_StatusCode st;
+
+ for (i = 0; i < iter; i++) {
+ st = P_SHA1_Hash_Generate (ctx, pBuffer + (i * SHA1_DIGEST_LENGTH));
+ if (st != UA_STATUSCODE_GOOD) {
+ UA_free (pBuffer);
+ UA_free (ctx);
+ return st;
}
}
- mbedtls_x509_crt_free(&remoteCertificate);
- return retval;
+ (void) memcpy (out->data, pBuffer, keyLen);
+ UA_free (pBuffer);
+ UA_free (ctx);
+
+ return UA_STATUSCODE_GOOD;
}
-static UA_StatusCode
-certificateVerification_verifyApplicationURI(void *verificationContext,
- const UA_ByteString *certificate,
- const UA_String *applicationURI) {
- CertInfo *ci = (CertInfo*)verificationContext;
- if(!ci)
+UA_StatusCode
+UA_OpenSSL_HMAC_SHA1_Verify (const UA_ByteString * message,
+ const UA_ByteString * key,
+ const UA_ByteString * signature
+ ) {
+ unsigned char buf[SHA1_DIGEST_LENGTH] = {0};
+ UA_ByteString mac = {SHA1_DIGEST_LENGTH, buf};
+
+ if(HMAC (EVP_sha1(), key->data, (int) key->length, message->data, message->length,
+ mac.data, (unsigned int *) &mac.length) == NULL) {
+ return UA_STATUSCODE_BADINTERNALERROR;
+ }
+ if (UA_ByteString_equal (signature, &mac)) {
+ return UA_STATUSCODE_GOOD;
+ }
+ else {
return UA_STATUSCODE_BADINTERNALERROR;
+ }
+}
- /* Parse the certificate */
- mbedtls_x509_crt remoteCertificate;
- mbedtls_x509_crt_init(&remoteCertificate);
- int mbedErr = mbedtls_x509_crt_parse(&remoteCertificate, certificate->data,
- certificate->length);
- if(mbedErr)
- return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
+UA_StatusCode
+UA_OpenSSL_HMAC_SHA1_Sign (const UA_ByteString * message,
+ const UA_ByteString * key,
+ UA_ByteString * signature
+ ) {
+ if (HMAC (EVP_sha1(), key->data, (int) key->length, message->data,
+ message->length,
+ signature->data, (unsigned int *) &(signature->length)) == NULL) {
+ return UA_STATUSCODE_BADINTERNALERROR;
+ }
+ return UA_STATUSCODE_GOOD;
+}
- /* Poor man's ApplicationUri verification. mbedTLS does not parse all fields
- * of the Alternative Subject Name. Instead test whether the URI-string is
- * present in the v3_ext field in general.
- *
- * TODO: Improve parsing of the Alternative Subject Name */
- UA_StatusCode retval = UA_STATUSCODE_GOOD;
- if(UA_Bstrstr(remoteCertificate.v3_ext.p, remoteCertificate.v3_ext.len,
- applicationURI->data, applicationURI->length) == NULL)
- retval = UA_STATUSCODE_BADCERTIFICATEURIINVALID;
+UA_StatusCode
+UA_Openssl_RSA_PKCS1_V15_Decrypt (UA_ByteString * data,
+ EVP_PKEY * privateKey) {
+ return UA_Openssl_RSA_Private_Decrypt (data, privateKey,
+ RSA_PKCS1_PADDING);
+}
- mbedtls_x509_crt_free(&remoteCertificate);
- return retval;
+UA_StatusCode
+UA_Openssl_RSA_PKCS1_V15_Encrypt (UA_ByteString * data,
+ size_t paddingSize,
+ X509 * publicX509) {
+ UA_ByteString message;
+ UA_StatusCode ret = UA_ByteString_copy (data, &message);
+ if (ret != UA_STATUSCODE_GOOD) {
+ return ret;
+ }
+ ret = UA_Openssl_RSA_Public_Encrypt (&message, publicX509,
+ RSA_PKCS1_PADDING,
+ paddingSize,
+ data);
+ UA_ByteString_clear (&message);
+ return ret;
}
-static void
-certificateVerification_clear(UA_CertificateVerification *cv) {
- CertInfo *ci = (CertInfo*)cv->context;
- if(!ci)
- return;
- mbedtls_x509_crt_free(&ci->certificateTrustList);
- mbedtls_x509_crl_free(&ci->certificateRevocationList);
- mbedtls_x509_crt_free(&ci->certificateIssuerList);
- UA_String_clear(&ci->trustListFolder);
- UA_String_clear(&ci->issuerListFolder);
- UA_String_clear(&ci->revocationListFolder);
- UA_free(ci);
- cv->context = NULL;
+UA_StatusCode
+UA_OpenSSL_AES_128_CBC_Decrypt (const UA_ByteString * iv,
+ const UA_ByteString * key,
+ UA_ByteString * data /* [in/out]*/
+ ) {
+ return UA_OpenSSL_Decrypt (iv, key, EVP_aes_128_cbc (), data);
}
UA_StatusCode
-UA_CertificateVerification_Trustlist(UA_CertificateVerification *cv,
- const UA_ByteString *certificateTrustList,
- size_t certificateTrustListSize,
- const UA_ByteString *certificateIssuerList,
- size_t certificateIssuerListSize,
- const UA_ByteString *certificateRevocationList,
- size_t certificateRevocationListSize) {
- CertInfo *ci = (CertInfo*)UA_malloc(sizeof(CertInfo));
- if(!ci)
- return UA_STATUSCODE_BADOUTOFMEMORY;
- memset(ci, 0, sizeof(CertInfo));
- mbedtls_x509_crt_init(&ci->certificateTrustList);
- mbedtls_x509_crl_init(&ci->certificateRevocationList);
- mbedtls_x509_crt_init(&ci->certificateIssuerList);
+UA_OpenSSL_AES_128_CBC_Encrypt (const UA_ByteString * iv,
+ const UA_ByteString * key,
+ UA_ByteString * data /* [in/out]*/
+ ) {
+ return UA_OpenSSL_Encrypt (iv, key, EVP_aes_128_cbc (), data);
+}
- cv->context = (void*)ci;
- if(certificateTrustListSize > 0)
- cv->verifyCertificate = certificateVerification_verify;
- else
- cv->verifyCertificate = verifyCertificateAllowAll;
- cv->clear = certificateVerification_clear;
- cv->verifyApplicationURI = certificateVerification_verifyApplicationURI;
+EVP_PKEY *
+UA_OpenSSL_LoadPrivateKey(const UA_ByteString *privateKey) {
+ const unsigned char * pkData = privateKey->data;
+ long len = (long) privateKey->length;
- int err = 0;
- UA_ByteString data;
- UA_ByteString_init(&data);
+ EVP_PKEY *result = NULL;
- for(size_t i = 0; i < certificateTrustListSize; i++) {
- data = copyDataFormatAware(&certificateTrustList[i]);
- err = mbedtls_x509_crt_parse(&ci->certificateTrustList,
- data.data,
- data.length);
- UA_ByteString_clear(&data);
- if(err)
- goto error;
- }
- for(size_t i = 0; i < certificateIssuerListSize; i++) {
- data = copyDataFormatAware(&certificateIssuerList[i]);
- err = mbedtls_x509_crt_parse(&ci->certificateIssuerList,
- data.data,
- data.length);
- UA_ByteString_clear(&data);
- if(err)
- goto error;
+ if (len > 1 && pkData[0] == 0x30 && pkData[1] == 0x82) { // Magic number for DER encoded keys
+ result = d2i_PrivateKey(EVP_PKEY_RSA, NULL,
+ &pkData, len);
+ } else {
+ BIO *bio = NULL;
+ bio = BIO_new_mem_buf((void *) privateKey->data, (int) privateKey->length);
+ result = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
+ BIO_free(bio);
}
- for(size_t i = 0; i < certificateRevocationListSize; i++) {
- data = copyDataFormatAware(&certificateRevocationList[i]);
- err = mbedtls_x509_crl_parse(&ci->certificateRevocationList,
- data.data,
- data.length);
- UA_ByteString_clear(&data);
- if(err)
- goto error;
+
+ return result;
+}
+
+X509 *
+UA_OpenSSL_LoadCertificate(const UA_ByteString *certificate) {
+ X509 * result = NULL;
+ const unsigned char *pData = certificate->data;
+
+ if (certificate->length > 1 && pData[0] == 0x30 && pData[1] == 0x82) { // Magic number for DER encoded files
+ result = UA_OpenSSL_LoadDerCertificate(certificate);
+ } else {
+ result = UA_OpenSSL_LoadPemCertificate(certificate);
}
- return UA_STATUSCODE_GOOD;
-error:
- certificateVerification_clear(cv);
- return UA_STATUSCODE_BADINTERNALERROR;
+ return result;
}
-#ifdef __linux__ /* Linux only so far */
+X509 *
+UA_OpenSSL_LoadDerCertificate(const UA_ByteString *certificate) {
+ const unsigned char *pData = certificate->data;
+ return d2i_X509(NULL, &pData, (long) certificate->length);
+}
+
+X509 *
+UA_OpenSSL_LoadPemCertificate(const UA_ByteString *certificate) {
+ X509 * result = NULL;
+
+ BIO* bio = NULL;
+ bio = BIO_new_mem_buf((void *) certificate->data, (int) certificate->length);
+ result = PEM_read_bio_X509(bio, NULL, NULL, NULL);
+ BIO_free(bio);
+
+ return result;
+}
UA_StatusCode
-UA_CertificateVerification_CertFolders(UA_CertificateVerification *cv,
- const char *trustListFolder,
- const char *issuerListFolder,
- const char *revocationListFolder) {
- CertInfo *ci = (CertInfo*)UA_malloc(sizeof(CertInfo));
- if(!ci)
- return UA_STATUSCODE_BADOUTOFMEMORY;
- memset(ci, 0, sizeof(CertInfo));
- mbedtls_x509_crt_init(&ci->certificateTrustList);
- mbedtls_x509_crl_init(&ci->certificateRevocationList);
- mbedtls_x509_crt_init(&ci->certificateIssuerList);
+UA_OpenSSL_LoadLocalCertificate(const UA_ByteString *certificate, UA_ByteString *target) {
+ X509 *cert = UA_OpenSSL_LoadCertificate(certificate);
- /* Only set the folder paths. They will be reloaded during runtime.
- * TODO: Add a more efficient reloading of only the changes */
- ci->trustListFolder = UA_STRING_ALLOC(trustListFolder);
- ci->issuerListFolder = UA_STRING_ALLOC(issuerListFolder);
- ci->revocationListFolder = UA_STRING_ALLOC(revocationListFolder);
+ if (!cert) {
+ UA_ByteString_init(target);
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+ }
- reloadCertificates(ci);
+ unsigned char *derData = NULL;
+ int length = i2d_X509(cert, &derData);
+ X509_free(cert);
- cv->context = (void*)ci;
- cv->verifyCertificate = certificateVerification_verify;
- cv->clear = certificateVerification_clear;
- cv->verifyApplicationURI = certificateVerification_verifyApplicationURI;
+ if (length > 0) {
+ UA_ByteString temp;
+ temp.length = (size_t) length;
+ temp.data = derData;
+ UA_ByteString_copy(&temp, target);
+ OPENSSL_free(derData);
+ return UA_STATUSCODE_GOOD;
+ } else {
+ UA_ByteString_init(target);
+ }
- return UA_STATUSCODE_GOOD;
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
}
#endif
-#endif
-
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/plugins/ua_nodestore_ziptree.c" ***********************************/
+/**** amalgamated original file "/plugins/crypto/openssl/ua_openssl_basic128rsa15.c" ****/
-/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
- * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
- * Copyright 2014-2018 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
- * Copyright 2017 (c) Julian Grothoff
- * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
+ * Copyright 2020 (c) Wind River Systems, Inc.
+ * Copyright 2020 (c) basysKom GmbH
*/
-#ifndef container_of
-#define container_of(ptr, type, member) \
- (type *)((uintptr_t)ptr - offsetof(type,member))
-#endif
+#if defined(UA_ENABLE_ENCRYPTION_OPENSSL) || defined(UA_ENABLE_ENCRYPTION_LIBRESSL)
-struct NodeEntry;
-typedef struct NodeEntry NodeEntry;
-struct NodeEntry {
- ZIP_ENTRY(NodeEntry) zipfields;
- UA_UInt32 nodeIdHash;
- UA_UInt16 refCount; /* How many consumers have a reference to the node? */
- UA_Boolean deleted; /* Node was marked as deleted and can be deleted when refCount == 0 */
- NodeEntry *orig; /* If a copy is made to replace a node, track that we
- * replace only the node from which the copy was made.
- * Important for concurrent operations. */
- UA_NodeId nodeId; /* This is actually a UA_Node that also starts with a NodeId */
-};
+#include <openssl/x509.h>
+#include <openssl/rand.h>
+#include <openssl/evp.h>
-/* Absolute ordering for NodeIds */
-static enum ZIP_CMP
-cmpNodeId(const void *a, const void *b) {
- const NodeEntry *aa = (const NodeEntry*)a;
- const NodeEntry *bb = (const NodeEntry*)b;
+#define UA_SHA1_LENGTH 20
+#define UA_SECURITYPOLICY_BASIC128RSA15_RSAPADDING_LEN 11
+#define UA_SECURITYPOLICY_BASIC128RSA15_SYM_ENCRYPTION_KEY_LENGTH 16
+#define UA_SECURITYPOLICY_BASIC128RSA15_SYM_ENCRYPTION_BLOCK_SIZE 16
+#define UA_SECURITYPOLICY_BASIC128RSA15_SYM_SIGNING_KEY_LENGTH 16
+#define UA_SHA1_LENGTH 20
- /* Compare hash */
- if(aa->nodeIdHash < bb->nodeIdHash)
- return ZIP_CMP_LESS;
- if(aa->nodeIdHash > bb->nodeIdHash)
- return ZIP_CMP_MORE;
+typedef struct {
+ EVP_PKEY * localPrivateKey;
+ UA_ByteString localCertThumbprint;
+ const UA_Logger * logger;
+} Policy_Context_Basic128Rsa15;
- /* Compore nodes in detail */
- return (enum ZIP_CMP)UA_NodeId_order(&aa->nodeId, &bb->nodeId);
-}
+typedef struct {
+ UA_ByteString localSymSigningKey;
+ UA_ByteString localSymEncryptingKey;
+ UA_ByteString localSymIv;
+ UA_ByteString remoteSymSigningKey;
+ UA_ByteString remoteSymEncryptingKey;
+ UA_ByteString remoteSymIv;
-ZIP_HEAD(NodeTree, NodeEntry);
-typedef struct NodeTree NodeTree;
+ Policy_Context_Basic128Rsa15 * policyContext;
+ UA_ByteString remoteCertificate;
+ X509 * remoteCertificateX509;
+} Channel_Context_Basic128Rsa15;
-typedef struct {
- NodeTree root;
-} ZipContext;
+static UA_StatusCode
+UA_Policy_Basic128Rsa15_New_Context (UA_SecurityPolicy * securityPolicy,
+ const UA_ByteString localPrivateKey,
+ const UA_Logger * logger) {
+ Policy_Context_Basic128Rsa15 * context = (Policy_Context_Basic128Rsa15 *)
+ UA_malloc (sizeof (Policy_Context_Basic128Rsa15));
+ if (context == NULL) {
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ }
+
+ context->localPrivateKey = UA_OpenSSL_LoadPrivateKey(&localPrivateKey);
-ZIP_PROTTYPE(NodeTree, NodeEntry, NodeEntry)
-ZIP_IMPL(NodeTree, NodeEntry, zipfields, NodeEntry, zipfields, cmpNodeId)
+ if (!context->localPrivateKey) {
+ UA_free(context);
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+ }
-static NodeEntry *
-newEntry(UA_NodeClass nodeClass) {
- size_t size = sizeof(NodeEntry) - sizeof(UA_NodeId);
- switch(nodeClass) {
- case UA_NODECLASS_OBJECT:
- size += sizeof(UA_ObjectNode);
- break;
- case UA_NODECLASS_VARIABLE:
- size += sizeof(UA_VariableNode);
- break;
- case UA_NODECLASS_METHOD:
- size += sizeof(UA_MethodNode);
- break;
- case UA_NODECLASS_OBJECTTYPE:
- size += sizeof(UA_ObjectTypeNode);
- break;
- case UA_NODECLASS_VARIABLETYPE:
- size += sizeof(UA_VariableTypeNode);
- break;
- case UA_NODECLASS_REFERENCETYPE:
- size += sizeof(UA_ReferenceTypeNode);
- break;
- case UA_NODECLASS_DATATYPE:
- size += sizeof(UA_DataTypeNode);
- break;
- case UA_NODECLASS_VIEW:
- size += sizeof(UA_ViewNode);
- break;
- default:
- return NULL;
+ UA_StatusCode retval = UA_Openssl_X509_GetCertificateThumbprint (
+ &securityPolicy->localCertificate,
+ &context->localCertThumbprint, true
+ );
+ if (retval != UA_STATUSCODE_GOOD) {
+ EVP_PKEY_free(context->localPrivateKey);
+ UA_free (context);
+ return retval;
}
- NodeEntry *entry = (NodeEntry*)UA_calloc(1, size);
- if(!entry)
- return NULL;
- UA_Node *node = (UA_Node*)&entry->nodeId;
- node->nodeClass = nodeClass;
- return entry;
-}
+
+ context->logger = logger;
+ securityPolicy->policyContext = context;
+
+ return UA_STATUSCODE_GOOD;
+}
static void
-deleteEntry(NodeEntry *entry) {
- UA_Node_clear((UA_Node*)&entry->nodeId);
- UA_free(entry);
+UA_Policy_Basic128Rsa15_Clear_Context (UA_SecurityPolicy *policy) {
+ if (policy == NULL) {
+ return;
+ }
+ UA_ByteString_clear(&policy->localCertificate);
+
+ Policy_Context_Basic128Rsa15 * ctx = (Policy_Context_Basic128Rsa15 *) policy->policyContext;
+ if (ctx == NULL) {
+ return;
+ }
+
+ /* delete all allocated members in the context */
+
+ EVP_PKEY_free(ctx->localPrivateKey);
+ UA_ByteString_clear(&ctx->localCertThumbprint);
+ UA_free (ctx);
+
+ return;
}
-static void
-cleanupEntry(NodeEntry *entry) {
- if(entry->deleted && entry->refCount == 0)
- deleteEntry(entry);
+/* create the channel context */
+
+static UA_StatusCode
+UA_ChannelModule_Basic128Rsa15_New_Context (const UA_SecurityPolicy * securityPolicy,
+ const UA_ByteString * remoteCertificate,
+ void ** channelContext) {
+ if (securityPolicy == NULL || remoteCertificate == NULL ||
+ channelContext == NULL) {
+ return UA_STATUSCODE_BADINTERNALERROR;
+ }
+ Channel_Context_Basic128Rsa15 * context = (Channel_Context_Basic128Rsa15 *)
+ UA_malloc (sizeof (Channel_Context_Basic128Rsa15));
+ if (context == NULL) {
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ }
+
+ UA_ByteString_init(&context->localSymSigningKey);
+ UA_ByteString_init(&context->localSymEncryptingKey);
+ UA_ByteString_init(&context->localSymIv);
+ UA_ByteString_init(&context->remoteSymSigningKey);
+ UA_ByteString_init(&context->remoteSymEncryptingKey);
+ UA_ByteString_init(&context->remoteSymIv);
+
+ UA_StatusCode retval = UA_copyCertificate (&context->remoteCertificate,
+ remoteCertificate);
+ if (retval != UA_STATUSCODE_GOOD) {
+ UA_free (context);
+ return retval;
+ }
+
+ /* decode to X509 */
+ context->remoteCertificateX509 = UA_OpenSSL_LoadCertificate(&context->remoteCertificate);
+ if (context->remoteCertificateX509 == NULL) {
+ UA_ByteString_clear (&context->remoteCertificate);
+ UA_free (context);
+ return UA_STATUSCODE_BADCERTIFICATECHAININCOMPLETE;
+ }
+
+ context->policyContext = (Policy_Context_Basic128Rsa15 *)
+ (securityPolicy->policyContext);
+
+ *channelContext = context;
+
+ UA_LOG_INFO (securityPolicy->logger,
+ UA_LOGCATEGORY_SECURITYPOLICY,
+ "The Basic128Rsa15 security policy channel with openssl is created.");
+
+ return UA_STATUSCODE_GOOD;
}
-/***********************/
-/* Interface functions */
-/***********************/
+/* delete the channel context */
-/* Not yet inserted into the ZipContext */
-static UA_Node *
-zipNsNewNode(void *nsCtx, UA_NodeClass nodeClass) {
- NodeEntry *entry = newEntry(nodeClass);
- if(!entry)
- return NULL;
- return (UA_Node*)&entry->nodeId;
+static void
+UA_ChannelModule_Basic128Rsa15_Delete_Context (void * channelContext) {
+ if (channelContext != NULL) {
+ Channel_Context_Basic128Rsa15 * cc = (Channel_Context_Basic128Rsa15 *)
+ channelContext;
+ X509_free (cc->remoteCertificateX509);
+ UA_ByteString_clear (&cc->remoteCertificate);
+ UA_ByteString_clear (&cc->localSymSigningKey);
+ UA_ByteString_clear (&cc->localSymEncryptingKey);
+ UA_ByteString_clear (&cc->localSymIv);
+ UA_ByteString_clear (&cc->remoteSymSigningKey);
+ UA_ByteString_clear (&cc->remoteSymEncryptingKey);
+ UA_ByteString_clear (&cc->remoteSymIv);
+ UA_LOG_INFO (cc->policyContext->logger,
+ UA_LOGCATEGORY_SECURITYPOLICY,
+ "The Basic128Rsa15 security policy channel with openssl is deleted.");
+
+ UA_free (cc);
+ }
}
-/* Not yet inserted into the ZipContext */
-static void
-zipNsDeleteNode(void *nsCtx, UA_Node *node) {
- deleteEntry(container_of(node, NodeEntry, nodeId));
+static UA_StatusCode
+UA_ChannelModule_Basic128Rsa15_setLocalSymSigningKey (void * channelContext,
+ const UA_ByteString * key) {
+ if (key == NULL || channelContext == NULL) {
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+ }
+
+ Channel_Context_Basic128Rsa15 * cc = (Channel_Context_Basic128Rsa15 *) channelContext;
+ UA_ByteString_clear(&cc->localSymSigningKey);
+ return UA_ByteString_copy(key, &cc->localSymSigningKey);
}
-static const UA_Node *
-zipNsGetNode(void *nsCtx, const UA_NodeId *nodeId) {
- ZipContext *ns = (ZipContext*)nsCtx;
- NodeEntry dummy;
- dummy.nodeIdHash = UA_NodeId_hash(nodeId);
- dummy.nodeId = *nodeId;
- NodeEntry *entry = ZIP_FIND(NodeTree, &ns->root, &dummy);
- if(!entry)
- return NULL;
- ++entry->refCount;
- return (const UA_Node*)&entry->nodeId;
+static UA_StatusCode
+UA_ChannelModule_Basic128Rsa15_setLocalSymEncryptingKey (void * channelContext,
+ const UA_ByteString * key) {
+ if (key == NULL || channelContext == NULL) {
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+ }
+
+ Channel_Context_Basic128Rsa15 * cc = (Channel_Context_Basic128Rsa15 *) channelContext;
+ UA_ByteString_clear(&cc->localSymEncryptingKey);
+ return UA_ByteString_copy(key, &cc->localSymEncryptingKey);
}
-static void
-zipNsReleaseNode(void *nsCtx, const UA_Node *node) {
- if(!node)
- return;
- NodeEntry *entry = container_of(node, NodeEntry, nodeId);
- UA_assert(entry->refCount > 0);
- --entry->refCount;
- cleanupEntry(entry);
+static UA_StatusCode
+UA_ChannelModule_Basic128Rsa15_setLocalSymIv (void * channelContext,
+ const UA_ByteString * iv) {
+ if (iv == NULL || channelContext == NULL) {
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+ }
+
+ Channel_Context_Basic128Rsa15 * cc = (Channel_Context_Basic128Rsa15 *) channelContext;
+ UA_ByteString_clear(&cc->localSymIv);
+ return UA_ByteString_copy(iv, &cc->localSymIv);
}
static UA_StatusCode
-zipNsGetNodeCopy(void *nsCtx, const UA_NodeId *nodeId,
- UA_Node **outNode) {
- /* Find the node */
- const UA_Node *node = zipNsGetNode(nsCtx, nodeId);
- if(!node)
- return UA_STATUSCODE_BADNODEIDUNKNOWN;
+UA_ChannelModule_Basic128Rsa15_setRemoteSymSigningKey (void * channelContext,
+ const UA_ByteString * key) {
+ if (key == NULL || channelContext == NULL) {
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+ }
- /* Create the new entry */
- NodeEntry *ne = newEntry(node->nodeClass);
- if(!ne) {
- zipNsReleaseNode(nsCtx, node);
- return UA_STATUSCODE_BADOUTOFMEMORY;
+ Channel_Context_Basic128Rsa15 * cc = (Channel_Context_Basic128Rsa15 *) channelContext;
+ UA_ByteString_clear(&cc->remoteSymSigningKey);
+ return UA_ByteString_copy(key, &cc->remoteSymSigningKey);
+}
+
+static UA_StatusCode
+UA_ChannelModule_Basic128Rsa15_setRemoteSymEncryptingKey (void * channelContext,
+ const UA_ByteString * key) {
+ if (key == NULL || channelContext == NULL) {
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
}
- /* Copy the node content */
- UA_Node *nnode = (UA_Node*)&ne->nodeId;
- UA_StatusCode retval = UA_Node_copy(node, nnode);
- zipNsReleaseNode(nsCtx, node);
- if(retval != UA_STATUSCODE_GOOD) {
- deleteEntry(ne);
- return retval;
+ Channel_Context_Basic128Rsa15 * cc = (Channel_Context_Basic128Rsa15 *) channelContext;
+ UA_ByteString_clear(&cc->remoteSymEncryptingKey);
+ return UA_ByteString_copy(key, &cc->remoteSymEncryptingKey);
+}
+
+static UA_StatusCode
+UA_ChannelModule_Basic128Rsa15_setRemoteSymIv (void * channelContext,
+ const UA_ByteString * key) {
+ if (key == NULL || channelContext == NULL) {
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
}
- ne->orig = container_of(node, NodeEntry, nodeId);
- *outNode = nnode;
- return UA_STATUSCODE_GOOD;
+ Channel_Context_Basic128Rsa15 * cc = (Channel_Context_Basic128Rsa15 *) channelContext;
+ UA_ByteString_clear(&cc->remoteSymIv);
+ return UA_ByteString_copy(key, &cc->remoteSymIv);
}
static UA_StatusCode
-zipNsInsertNode(void *nsCtx, UA_Node *node, UA_NodeId *addedNodeId) {
- NodeEntry *entry = container_of(node, NodeEntry, nodeId);
- ZipContext *ns = (ZipContext*)nsCtx;
+UA_ChannelModule_Basic128Rsa15_compareCertificate (const void * channelContext,
+ const UA_ByteString * certificate) {
+ if(channelContext == NULL || certificate == NULL) {
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+ }
- /* Ensure that the NodeId is unique */
- NodeEntry dummy;
- dummy.nodeId = node->nodeId;
- if(node->nodeId.identifierType == UA_NODEIDTYPE_NUMERIC &&
- node->nodeId.identifier.numeric == 0) {
- do { /* Create a random nodeid until we find an unoccupied id */
- node->nodeId.identifier.numeric = UA_UInt32_random();
- dummy.nodeId.identifier.numeric = node->nodeId.identifier.numeric;
- dummy.nodeIdHash = UA_NodeId_hash(&node->nodeId);
- } while(ZIP_FIND(NodeTree, &ns->root, &dummy));
- } else {
- dummy.nodeIdHash = UA_NodeId_hash(&node->nodeId);
- if(ZIP_FIND(NodeTree, &ns->root, &dummy)) { /* The nodeid exists */
- deleteEntry(entry);
- return UA_STATUSCODE_BADNODEIDEXISTS;
- }
+ const Channel_Context_Basic128Rsa15 * cc =
+ (const Channel_Context_Basic128Rsa15 *) channelContext;
+ return UA_OpenSSL_X509_compare (certificate, cc->remoteCertificateX509);
+}
+
+static UA_StatusCode
+UA_Asy_Basic128Rsa15_compareCertificateThumbprint (const UA_SecurityPolicy * securityPolicy,
+ const UA_ByteString * certificateThumbprint) {
+ if (securityPolicy == NULL || certificateThumbprint == NULL) {
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+ }
+ Policy_Context_Basic128Rsa15 *pc = (Policy_Context_Basic128Rsa15 *)
+ securityPolicy->policyContext;
+ if(!UA_ByteString_equal(certificateThumbprint, &pc->localCertThumbprint)) {
+ return UA_STATUSCODE_BADCERTIFICATEINVALID;
}
+ return UA_STATUSCODE_GOOD;
+}
- /* Copy the NodeId */
- if(addedNodeId) {
- UA_StatusCode retval = UA_NodeId_copy(&node->nodeId, addedNodeId);
- if(retval != UA_STATUSCODE_GOOD) {
- deleteEntry(entry);
- return retval;
- }
+/* Generates a thumbprint for the specified certificate */
+
+static UA_StatusCode
+UA_Asy_Basic128Rsa15_makeCertificateThumbprint (const UA_SecurityPolicy * securityPolicy,
+ const UA_ByteString * certificate,
+ UA_ByteString * thumbprint) {
+ return UA_Openssl_X509_GetCertificateThumbprint (certificate,
+ thumbprint, false);
+}
+
+static size_t
+UA_AsySig_Basic128Rsa15_getRemoteSignatureSize (const void * channelContext) {
+ if (channelContext == NULL) {
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
}
- /* Insert the node */
- entry->nodeIdHash = dummy.nodeIdHash;
- ZIP_INSERT(NodeTree, &ns->root, entry, ZIP_FFS32(UA_UInt32_random()));
- return UA_STATUSCODE_GOOD;
+ const Channel_Context_Basic128Rsa15 * cc = (const Channel_Context_Basic128Rsa15 *) channelContext;
+ UA_Int32 keyLen = 0;
+ UA_Openssl_RSA_Public_GetKeyLength (cc->remoteCertificateX509, &keyLen);
+ return (size_t) keyLen;
+}
+
+static size_t
+UA_AsySig_Basic128Rsa15_getLocalSignatureSize (const void * channelContext) {
+ if (channelContext == NULL) {
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+ }
+
+ const Channel_Context_Basic128Rsa15 * cc = (const Channel_Context_Basic128Rsa15 *) channelContext;
+ Policy_Context_Basic128Rsa15 * pc = (Policy_Context_Basic128Rsa15 *) cc->policyContext;
+ UA_Int32 keyLen = 0;
+ UA_Openssl_RSA_Private_GetKeyLength (pc->localPrivateKey, &keyLen);
+
+ return (size_t) keyLen;
+}
+
+static UA_StatusCode
+UA_AsySig_Basic128Rsa15_Verify (void * channelContext,
+ const UA_ByteString * message,
+ const UA_ByteString * signature) {
+ if (message == NULL || signature == NULL ||
+ channelContext == NULL) {
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+ }
+
+ Channel_Context_Basic128Rsa15 * cc = (Channel_Context_Basic128Rsa15 *) channelContext;
+ UA_StatusCode retval = UA_OpenSSL_RSA_PKCS1_V15_SHA1_Verify (message,
+ cc->remoteCertificateX509, signature);
+
+ return retval;
}
static UA_StatusCode
-zipNsReplaceNode(void *nsCtx, UA_Node *node) {
- /* Find the node */
- const UA_Node *oldNode = zipNsGetNode(nsCtx, &node->nodeId);
- if(!oldNode) {
- deleteEntry(container_of(node, NodeEntry, nodeId));
- return UA_STATUSCODE_BADNODEIDUNKNOWN;
+UA_AsySig_Basic128Rsa15_Sign (void * channelContext,
+ const UA_ByteString * message,
+ UA_ByteString * signature) {
+ if (channelContext == NULL || message == NULL || signature == NULL) {
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
}
- /* Test if the copy is current */
- NodeEntry *entry = container_of(node, NodeEntry, nodeId);
- NodeEntry *oldEntry = container_of(oldNode, NodeEntry, nodeId);
- if(oldEntry != entry->orig) {
- /* The node was already updated since the copy was made */
- deleteEntry(entry);
- zipNsReleaseNode(nsCtx, oldNode);
- return UA_STATUSCODE_BADINTERNALERROR;
+ const Channel_Context_Basic128Rsa15 * cc = (const Channel_Context_Basic128Rsa15 *) channelContext;
+ Policy_Context_Basic128Rsa15 *pc = cc->policyContext;
+ return UA_Openssl_RSA_PKCS1_V15_SHA1_Sign (message, pc->localPrivateKey, signature);
+}
+
+static size_t
+UA_AsymEn_Basic128Rsa15_getRemotePlainTextBlockSize (const void *channelContext) {
+ if (channelContext == NULL) {
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
}
- /* Replace */
- ZipContext *ns = (ZipContext*)nsCtx;
- ZIP_REMOVE(NodeTree, &ns->root, oldEntry);
- entry->nodeIdHash = oldEntry->nodeIdHash;
- ZIP_INSERT(NodeTree, &ns->root, entry, ZIP_RANK(entry, zipfields));
- oldEntry->deleted = true;
+ const Channel_Context_Basic128Rsa15 * cc = (const Channel_Context_Basic128Rsa15 *) channelContext;
+ UA_Int32 keyLen = 0;
+ UA_Openssl_RSA_Public_GetKeyLength (cc->remoteCertificateX509, &keyLen);
+ return (size_t) keyLen - UA_SECURITYPOLICY_BASIC128RSA15_RSAPADDING_LEN;
+}
- zipNsReleaseNode(nsCtx, oldNode);
- return UA_STATUSCODE_GOOD;
+static size_t
+UA_AsymEn_Basic128Rsa15_getRemoteBlockSize (const void *channelContext) {
+ if (channelContext == NULL) {
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+ }
+
+ const Channel_Context_Basic128Rsa15 * cc = (const Channel_Context_Basic128Rsa15 *) channelContext;
+ UA_Int32 keyLen = 0;
+ UA_Openssl_RSA_Public_GetKeyLength (cc->remoteCertificateX509, &keyLen);
+ return (size_t) keyLen;
+}
+
+static size_t
+UA_AsymEn_Basic128Rsa15_getRemoteKeyLength (const void *channelContext) {
+ if (channelContext == NULL)
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+
+ const Channel_Context_Basic128Rsa15 * cc = (const Channel_Context_Basic128Rsa15 *) channelContext;
+ UA_Int32 keyLen = 0;
+ UA_Openssl_RSA_Public_GetKeyLength (cc->remoteCertificateX509, &keyLen);
+ return (size_t) keyLen * 8;
+}
+
+static size_t
+UA_AsymEn_Basic128Rsa15_getLocalKeyLength (const void *channelContext) {
+ if (channelContext == NULL)
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+
+ const Channel_Context_Basic128Rsa15 *cc = (const Channel_Context_Basic128Rsa15 *) channelContext;
+ Policy_Context_Basic128Rsa15 *pc = cc->policyContext;
+ UA_Int32 keyLen = 0;
+ UA_Openssl_RSA_Private_GetKeyLength (pc->localPrivateKey, &keyLen);
+ return (size_t) keyLen * 8;
+}
+
+static UA_StatusCode
+UA_AsymEn_Basic128Rsa15_Decrypt (void * channelContext,
+ UA_ByteString * data) {
+ if (channelContext == NULL || data == NULL) {
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+ }
+
+ Channel_Context_Basic128Rsa15 * cc = (Channel_Context_Basic128Rsa15 *) channelContext;
+ UA_StatusCode ret = UA_Openssl_RSA_PKCS1_V15_Decrypt (data,
+ cc->policyContext->localPrivateKey);
+ return ret;
}
static UA_StatusCode
-zipNsRemoveNode(void *nsCtx, const UA_NodeId *nodeId) {
- ZipContext *ns = (ZipContext*)nsCtx;
- NodeEntry dummy;
- dummy.nodeIdHash = UA_NodeId_hash(nodeId);
- dummy.nodeId = *nodeId;
- NodeEntry *entry = ZIP_FIND(NodeTree, &ns->root, &dummy);
- if(!entry)
- return UA_STATUSCODE_BADNODEIDUNKNOWN;
- ZIP_REMOVE(NodeTree, &ns->root, entry);
- entry->deleted = true;
- cleanupEntry(entry);
+UA_AsymEn_Basic128Rsa15_Encrypt (void * channelContext,
+ UA_ByteString * data) {
+ if (channelContext == NULL || data == NULL)
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+
+ Channel_Context_Basic128Rsa15 * cc = (Channel_Context_Basic128Rsa15 *) channelContext;
+ return UA_Openssl_RSA_PKCS1_V15_Encrypt (data,
+ UA_SECURITYPOLICY_BASIC128RSA15_RSAPADDING_LEN,
+ cc->remoteCertificateX509);
+}
+
+static UA_StatusCode
+UA_Sym_Basic128Rsa15_generateNonce(void *policyContext,
+ UA_ByteString *out) {
+ UA_Int32 rc = RAND_bytes(out->data, (int) out->length);
+ if (rc != 1) {
+ return UA_STATUSCODE_BADUNEXPECTEDERROR;
+ }
return UA_STATUSCODE_GOOD;
}
-struct VisitorData {
- UA_NodestoreVisitor visitor;
- void *visitorContext;
-};
+static UA_StatusCode
+UA_Sym_Basic128Rsa15_generateKey(void *policyContext,
+ const UA_ByteString *secret,
+ const UA_ByteString *seed,
+ UA_ByteString *out) {
+ return UA_Openssl_Random_Key_PSHA1_Derive(secret, seed, out);
+}
-static void
-nodeVisitor(NodeEntry *entry, void *data) {
- struct VisitorData *d = (struct VisitorData*)data;
- d->visitor(d->visitorContext, (UA_Node*)&entry->nodeId);
+static size_t
+UA_SymEn_Basic128Rsa15_getLocalKeyLength (const void *channelContext) {
+ /* 16 bytes 128 bits */
+ return UA_SECURITYPOLICY_BASIC128RSA15_SYM_ENCRYPTION_KEY_LENGTH;
}
-static void
-zipNsIterate(void *nsCtx, UA_NodestoreVisitor visitor,
- void *visitorCtx) {
- struct VisitorData d;
- d.visitor = visitor;
- d.visitorContext = visitorCtx;
- ZipContext *ns = (ZipContext*)nsCtx;
- ZIP_ITER(NodeTree, &ns->root, nodeVisitor, &d);
+static size_t
+UA_SymEn_Basic128Rsa15_getBlockSize (const void *channelContext) {
+ return UA_SECURITYPOLICY_BASIC128RSA15_SYM_ENCRYPTION_BLOCK_SIZE;
}
-static void
-deleteNodeVisitor(NodeEntry *entry, void *data) {
- deleteEntry(entry);
+static size_t
+UA_SymEn_Basic128Rsa15_getRemoteKeyLength (const void * channelContext) {
+ return UA_SECURITYPOLICY_BASIC128RSA15_SYM_ENCRYPTION_KEY_LENGTH;
}
-/***********************/
-/* Nodestore Lifecycle */
-/***********************/
+static UA_StatusCode
+UA_SymEn_Basic128Rsa15_Encrypt (void *channelContext,
+ UA_ByteString *data) {
+ if(channelContext == NULL || data == NULL)
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+
+ Channel_Context_Basic128Rsa15 * cc = (Channel_Context_Basic128Rsa15 *) channelContext;
+ return UA_OpenSSL_AES_128_CBC_Encrypt (&cc->localSymIv, &cc->localSymEncryptingKey, data);
+}
-static void
-zipNsClear(void *nsCtx) {
- if (!nsCtx)
- return;
- ZipContext *ns = (ZipContext*)nsCtx;
- ZIP_ITER(NodeTree, &ns->root, deleteNodeVisitor, NULL);
- UA_free(ns);
+static UA_StatusCode
+UA_SymEn_Basic128Rsa15_Decrypt (void * channelContext,
+ UA_ByteString * data) {
+ if(channelContext == NULL || data == NULL)
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+ Channel_Context_Basic128Rsa15 * cc = (Channel_Context_Basic128Rsa15 *) channelContext;
+ return UA_OpenSSL_AES_128_CBC_Decrypt (&cc->remoteSymIv, &cc->remoteSymEncryptingKey, data);
}
-UA_StatusCode
-UA_Nodestore_ZipTree(UA_Nodestore *ns) {
- /* Allocate and initialize the context */
- ZipContext *ctx = (ZipContext*)UA_malloc(sizeof(ZipContext));
- if(!ctx)
- return UA_STATUSCODE_BADOUTOFMEMORY;
+static size_t
+UA_SymSig_Basic128Rsa15_getKeyLength (const void *channelContext) {
+ return UA_SECURITYPOLICY_BASIC128RSA15_SYM_SIGNING_KEY_LENGTH;
+}
- ZIP_INIT(&ctx->root);
+static size_t
+UA_SymSig_Basic128Rsa15_getSignatureSize (const void *channelContext) {
+ return UA_SHA1_LENGTH;
+}
- /* Populate the nodestore */
- ns->context = (void*)ctx;
- ns->clear = zipNsClear;
- ns->newNode = zipNsNewNode;
- ns->deleteNode = zipNsDeleteNode;
- ns->getNode = zipNsGetNode;
- ns->releaseNode = zipNsReleaseNode;
- ns->getNodeCopy = zipNsGetNodeCopy;
- ns->insertNode = zipNsInsertNode;
- ns->replaceNode = zipNsReplaceNode;
- ns->removeNode = zipNsRemoveNode;
- ns->iterate = zipNsIterate;
+static UA_StatusCode
+UA_SymSig_Basic128Rsa15_Verify (void * channelContext,
+ const UA_ByteString * message,
+ const UA_ByteString * signature) {
+ if (channelContext == NULL || message == NULL || signature == NULL)
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+
+ Channel_Context_Basic128Rsa15 * cc = (Channel_Context_Basic128Rsa15 *) channelContext;
+ return UA_OpenSSL_HMAC_SHA1_Verify (message,
+ &cc->remoteSymSigningKey,
+ signature);
+}
+
+static UA_StatusCode
+UA_SymSig_Basic128Rsa15_Sign (void * channelContext,
+ const UA_ByteString * message,
+ UA_ByteString * signature) {
+ if (channelContext == NULL || message == NULL || signature == NULL)
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+ Channel_Context_Basic128Rsa15 * cc = (Channel_Context_Basic128Rsa15 *) channelContext;
+ return UA_OpenSSL_HMAC_SHA1_Sign (message, &cc->localSymSigningKey, signature);
+}
+
+/* the main entry of Basic128Rsa15 */
+
+UA_StatusCode
+UA_SecurityPolicy_Basic128Rsa15 (UA_SecurityPolicy * policy,
+ const UA_ByteString localCertificate,
+ const UA_ByteString localPrivateKey,
+ const UA_Logger * logger) {
+
+ UA_SecurityPolicyAsymmetricModule * const asymmetricModule = &policy->asymmetricModule;
+ UA_SecurityPolicySymmetricModule * const symmetricModule = &policy->symmetricModule;
+ UA_SecurityPolicyChannelModule * const channelModule = &policy->channelModule;
+ UA_StatusCode retval;
+
+ UA_LOG_INFO (logger, UA_LOGCATEGORY_SECURITYPOLICY,
+ "The Basic128Rsa15 security policy with openssl is added.");
+
+ UA_Openssl_Init ();
+ memset(policy, 0, sizeof(UA_SecurityPolicy));
+ policy->logger = logger;
+ policy->policyUri = UA_STRING("http://opcfoundation.org/UA/SecurityPolicy#Basic128Rsa15\0");
+
+ /* set ChannelModule context */
+
+ channelModule->newContext = UA_ChannelModule_Basic128Rsa15_New_Context;
+ channelModule->deleteContext = UA_ChannelModule_Basic128Rsa15_Delete_Context;
+
+ channelModule->setLocalSymSigningKey = UA_ChannelModule_Basic128Rsa15_setLocalSymSigningKey;
+ channelModule->setLocalSymEncryptingKey = UA_ChannelModule_Basic128Rsa15_setLocalSymEncryptingKey;
+ channelModule->setLocalSymIv = UA_ChannelModule_Basic128Rsa15_setLocalSymIv;
+ channelModule->setRemoteSymSigningKey = UA_ChannelModule_Basic128Rsa15_setRemoteSymSigningKey;
+ channelModule->setRemoteSymEncryptingKey = UA_ChannelModule_Basic128Rsa15_setRemoteSymEncryptingKey;
+ channelModule->setRemoteSymIv = UA_ChannelModule_Basic128Rsa15_setRemoteSymIv;
+ channelModule->compareCertificate = UA_ChannelModule_Basic128Rsa15_compareCertificate;
+
+ retval = UA_OpenSSL_LoadLocalCertificate(&localCertificate, &policy->localCertificate);
+
+ if (retval != UA_STATUSCODE_GOOD)
+ return retval;
+
+ /* asymmetricModule */
+
+ asymmetricModule->compareCertificateThumbprint = UA_Asy_Basic128Rsa15_compareCertificateThumbprint;
+ asymmetricModule->makeCertificateThumbprint = UA_Asy_Basic128Rsa15_makeCertificateThumbprint;
+
+ /* AsymmetricModule - signature algorithm */
+
+ UA_SecurityPolicySignatureAlgorithm * asySigAlgorithm =
+ &asymmetricModule->cryptoModule.signatureAlgorithm;
+ asySigAlgorithm->uri = UA_STRING("http://www.w3.org/2000/09/xmldsig#rsa-sha1\0");
+ asySigAlgorithm->getRemoteSignatureSize = UA_AsySig_Basic128Rsa15_getRemoteSignatureSize;
+ asySigAlgorithm->getLocalSignatureSize = UA_AsySig_Basic128Rsa15_getLocalSignatureSize;
+ asySigAlgorithm->getLocalKeyLength = NULL;
+ asySigAlgorithm->getRemoteKeyLength = NULL;
+ asySigAlgorithm->verify = UA_AsySig_Basic128Rsa15_Verify;
+ asySigAlgorithm->sign = UA_AsySig_Basic128Rsa15_Sign;
+
+ /* AsymmetricModule encryption algorithm */
+
+ UA_SecurityPolicyEncryptionAlgorithm * asymEncryAlg =
+ &asymmetricModule->cryptoModule.encryptionAlgorithm;
+ asymEncryAlg->uri = UA_STRING("http://www.w3.org/2001/04/xmlenc#rsa-1_5\0");
+ asymEncryAlg->getRemotePlainTextBlockSize = UA_AsymEn_Basic128Rsa15_getRemotePlainTextBlockSize;
+ asymEncryAlg->getRemoteBlockSize = UA_AsymEn_Basic128Rsa15_getRemoteBlockSize;
+ asymEncryAlg->getRemoteKeyLength = UA_AsymEn_Basic128Rsa15_getRemoteKeyLength;
+ asymEncryAlg->getLocalKeyLength = UA_AsymEn_Basic128Rsa15_getLocalKeyLength;
+ asymEncryAlg->decrypt = UA_AsymEn_Basic128Rsa15_Decrypt;
+ asymEncryAlg->encrypt = UA_AsymEn_Basic128Rsa15_Encrypt;
+
+ /* SymmetricModule */
+
+ symmetricModule->secureChannelNonceLength = 16; /* 128 bits*/
+ symmetricModule->generateNonce = UA_Sym_Basic128Rsa15_generateNonce;
+ symmetricModule->generateKey = UA_Sym_Basic128Rsa15_generateKey;
+
+ /* Symmetric encryption Algorithm */
+
+ UA_SecurityPolicyEncryptionAlgorithm * symEncryptionAlgorithm =
+ &symmetricModule->cryptoModule.encryptionAlgorithm;
+ symEncryptionAlgorithm->uri = UA_STRING("http://www.w3.org/2001/04/xmlenc#aes128-cbc\0");
+ symEncryptionAlgorithm->getLocalKeyLength = UA_SymEn_Basic128Rsa15_getLocalKeyLength;
+ symEncryptionAlgorithm->getRemoteKeyLength = UA_SymEn_Basic128Rsa15_getRemoteKeyLength;
+ symEncryptionAlgorithm->getRemoteBlockSize = UA_SymEn_Basic128Rsa15_getBlockSize;
+ symEncryptionAlgorithm->getRemotePlainTextBlockSize = UA_SymEn_Basic128Rsa15_getBlockSize;
+ symEncryptionAlgorithm->decrypt = UA_SymEn_Basic128Rsa15_Decrypt;
+ symEncryptionAlgorithm->encrypt = UA_SymEn_Basic128Rsa15_Encrypt;
+
+ /* Symmetric signature Algorithm */
+
+ UA_SecurityPolicySignatureAlgorithm * symSignatureAlgorithm =
+ &symmetricModule->cryptoModule.signatureAlgorithm;
+ symSignatureAlgorithm->uri = UA_STRING("http://www.w3.org/2000/09/xmldsig#hmac-sha1\0");
+ symSignatureAlgorithm->getLocalKeyLength = UA_SymSig_Basic128Rsa15_getKeyLength;
+ symSignatureAlgorithm->getRemoteKeyLength = UA_SymSig_Basic128Rsa15_getKeyLength;
+ symSignatureAlgorithm->getRemoteSignatureSize = UA_SymSig_Basic128Rsa15_getSignatureSize;
+ symSignatureAlgorithm->getLocalSignatureSize = UA_SymSig_Basic128Rsa15_getSignatureSize;
+
+ symSignatureAlgorithm->verify = UA_SymSig_Basic128Rsa15_Verify;
+ symSignatureAlgorithm->sign = UA_SymSig_Basic128Rsa15_Sign;
+
+ /* set the policy context */
+
+ retval = UA_Policy_Basic128Rsa15_New_Context (policy, localPrivateKey, logger);
+ if (retval != UA_STATUSCODE_GOOD) {
+ UA_ByteString_clear (&policy->localCertificate);
+ return retval;
+ }
+ policy->clear = UA_Policy_Basic128Rsa15_Clear_Context;
+
+ /* Use the same signature algorithm as the asymmetric component for
+ certificate signing (see standard) */
+ policy->certificateSigningAlgorithm = policy->asymmetricModule.cryptoModule.signatureAlgorithm;
+
return UA_STATUSCODE_GOOD;
}
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/plugins/ua_nodestore_hashmap.c" ***********************************/
+#endif
-/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
- * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
+/**** amalgamated original file "/plugins/crypto/openssl/ua_openssl_basic256.c" ****/
+
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
- * Copyright 2014-2019 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
- * Copyright 2017 (c) Julian Grothoff
- * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
+ * Copyright 2020 (c) Wind River Systems, Inc.
+ * Copyright 2020 (c) basysKom GmbH
*/
-#ifndef container_of
-#define container_of(ptr, type, member) \
- (type *)((uintptr_t)ptr - offsetof(type,member))
-#endif
+#if defined(UA_ENABLE_ENCRYPTION_OPENSSL) || defined(UA_ENABLE_ENCRYPTION_LIBRESSL)
-/* The default Nodestore is simply a hash-map from NodeIds to Nodes. To find an
- * entry, iterate over candidate positions according to the NodeId hash.
- *
- * - Tombstone or non-matching NodeId: continue searching
- * - Matching NodeId: Return the entry
- * - NULL: Abort the search */
-typedef struct UA_NodeMapEntry {
- struct UA_NodeMapEntry *orig; /* the version this is a copy from (or NULL) */
- UA_UInt16 refCount; /* How many consumers have a reference to the node? */
- UA_Boolean deleted; /* Node was marked as deleted and can be deleted when refCount == 0 */
- UA_Node node;
-} UA_NodeMapEntry;
+#include <openssl/x509.h>
+#include <openssl/rand.h>
-#define UA_NODEMAP_MINSIZE 64
-#define UA_NODEMAP_TOMBSTONE ((UA_NodeMapEntry*)0x01)
+#define UA_SECURITYPOLICY_BASIC256SHA1_RSAPADDING_LEN 42
+#define UA_SECURITYPOLICY_BASIC256_SYM_ENCRYPTION_KEY_LENGTH 32
+#define UA_SECURITYPOLICY_BASIC256_SYM_ENCRYPTION_BLOCK_SIZE 16
+#define UA_SECURITYPOLICY_BASIC256_SYM_SIGNING_KEY_LENGTH 24
+#define UA_SHA1_LENGTH 20
typedef struct {
- UA_NodeMapEntry *entry;
- UA_UInt32 nodeIdHash;
-} UA_NodeMapSlot;
+ EVP_PKEY * localPrivateKey;
+ UA_ByteString localCertThumbprint;
+ const UA_Logger * logger;
+} Policy_Context_Basic256;
typedef struct {
- UA_NodeMapSlot *slots;
- UA_UInt32 size;
- UA_UInt32 count;
- UA_UInt32 sizePrimeIndex;
-} UA_NodeMap;
+ UA_ByteString localSymSigningKey;
+ UA_ByteString localSymEncryptingKey;
+ UA_ByteString localSymIv;
+ UA_ByteString remoteSymSigningKey;
+ UA_ByteString remoteSymEncryptingKey;
+ UA_ByteString remoteSymIv;
-/*********************/
-/* HashMap Utilities */
-/*********************/
+ Policy_Context_Basic256 * policyContext;
+ UA_ByteString remoteCertificate;
+ X509 * remoteCertificateX509;
+} Channel_Context_Basic256;
-/* The size of the hash-map is always a prime number. They are chosen to be
- * close to the next power of 2. So the size ca. doubles with each prime. */
-static UA_UInt32 const primes[] = {
- 7, 13, 31, 61, 127, 251,
- 509, 1021, 2039, 4093, 8191, 16381,
- 32749, 65521, 131071, 262139, 524287, 1048573,
- 2097143, 4194301, 8388593, 16777213, 33554393, 67108859,
- 134217689, 268435399, 536870909, 1073741789, 2147483647, 4294967291
-};
+static UA_StatusCode
+UA_Policy_Basic256_New_Context (UA_SecurityPolicy * securityPolicy,
+ const UA_ByteString localPrivateKey,
+ const UA_Logger * logger) {
+ Policy_Context_Basic256 * context = (Policy_Context_Basic256 *)
+ UA_malloc (sizeof (Policy_Context_Basic256));
+ if (context == NULL) {
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ }
+
+ context->localPrivateKey = UA_OpenSSL_LoadPrivateKey(&localPrivateKey);
-static UA_UInt32 mod(UA_UInt32 h, UA_UInt32 size) { return h % size; }
-static UA_UInt32 mod2(UA_UInt32 h, UA_UInt32 size) { return 1 + (h % (size - 2)); }
+ if (!context->localPrivateKey) {
+ UA_free (context);
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+ }
-static UA_UInt16
-higher_prime_index(UA_UInt32 n) {
- UA_UInt16 low = 0;
- UA_UInt16 high = (UA_UInt16)(sizeof(primes) / sizeof(UA_UInt32));
- while(low != high) {
- UA_UInt16 mid = (UA_UInt16)(low + ((high - low) / 2));
- if(n > primes[mid])
- low = (UA_UInt16)(mid + 1);
- else
- high = mid;
+ UA_StatusCode retval = UA_Openssl_X509_GetCertificateThumbprint (
+ &securityPolicy->localCertificate,
+ &context->localCertThumbprint, true
+ );
+ if (retval != UA_STATUSCODE_GOOD) {
+ EVP_PKEY_free(context->localPrivateKey);
+ UA_free (context);
+ return retval;
}
- return low;
-}
-/* Returns an empty slot or null if the nodeid exists or if no empty slot is found. */
-static UA_NodeMapSlot *
-findFreeSlot(const UA_NodeMap *ns, const UA_NodeId *nodeid) {
- UA_UInt32 h = UA_NodeId_hash(nodeid);
- UA_UInt32 size = ns->size;
- UA_UInt64 idx = mod(h, size); /* Use 64bit container to avoid overflow */
- UA_UInt32 startIdx = (UA_UInt32)idx;
- UA_UInt32 hash2 = mod2(h, size);
+ context->logger = logger;
+ securityPolicy->policyContext = context;
- UA_NodeMapSlot *candidate = NULL;
- do {
- UA_NodeMapSlot *slot = &ns->slots[(UA_UInt32)idx];
+ return UA_STATUSCODE_GOOD;
+}
- if(slot->entry > UA_NODEMAP_TOMBSTONE) {
- /* A Node with the NodeId does already exist */
- if(slot->nodeIdHash == h &&
- UA_NodeId_equal(&slot->entry->node.nodeId, nodeid))
- return NULL;
- } else {
- /* Found a candidate node */
- if(!candidate)
- candidate = slot;
- /* No matching node can come afterwards */
- if(slot->entry == NULL)
- return candidate;
- }
+static void
+UA_Policy_Basic256_Clear_Context (UA_SecurityPolicy *policy) {
+ if (policy == NULL) {
+ return;
+ }
+ UA_ByteString_clear(&policy->localCertificate);
- idx += hash2;
- if(idx >= size)
- idx -= size;
- } while((UA_UInt32)idx != startIdx);
+ Policy_Context_Basic256 * ctx = (Policy_Context_Basic256 *) policy->policyContext;
+ if (ctx == NULL) {
+ return;
+ }
- return candidate;
+ /* delete all allocated members in the context */
+
+ EVP_PKEY_free(ctx->localPrivateKey);
+ UA_ByteString_clear(&ctx->localCertThumbprint);
+ UA_free (ctx);
+
+ return;
}
-/* The occupancy of the table after the call will be about 50% */
-static UA_StatusCode
-expand(UA_NodeMap *ns) {
- UA_UInt32 osize = ns->size;
- UA_UInt32 count = ns->count;
- /* Resize only when table after removal of unused elements is either too
- full or too empty */
- if(count * 2 < osize && (count * 8 > osize || osize <= UA_NODEMAP_MINSIZE))
- return UA_STATUSCODE_GOOD;
+/* create the channel context */
- UA_NodeMapSlot *oslots = ns->slots;
- UA_UInt32 nindex = higher_prime_index(count * 2);
- UA_UInt32 nsize = primes[nindex];
- UA_NodeMapSlot *nslots= (UA_NodeMapSlot*)UA_calloc(nsize, sizeof(UA_NodeMapSlot));
- if(!nslots)
+static UA_StatusCode
+UA_ChannelModule_Basic256_New_Context (const UA_SecurityPolicy * securityPolicy,
+ const UA_ByteString * remoteCertificate,
+ void ** channelContext) {
+ if (securityPolicy == NULL || remoteCertificate == NULL ||
+ channelContext == NULL) {
+ return UA_STATUSCODE_BADINTERNALERROR;
+ }
+ Channel_Context_Basic256 * context = (Channel_Context_Basic256 *)
+ UA_malloc (sizeof (Channel_Context_Basic256));
+ if (context == NULL) {
return UA_STATUSCODE_BADOUTOFMEMORY;
+ }
- ns->slots = nslots;
- ns->size = nsize;
- ns->sizePrimeIndex = nindex;
+ UA_ByteString_init(&context->localSymSigningKey);
+ UA_ByteString_init(&context->localSymEncryptingKey);
+ UA_ByteString_init(&context->localSymIv);
+ UA_ByteString_init(&context->remoteSymSigningKey);
+ UA_ByteString_init(&context->remoteSymEncryptingKey);
+ UA_ByteString_init(&context->remoteSymIv);
- /* recompute the position of every entry and insert the pointer */
- for(size_t i = 0, j = 0; i < osize && j < count; ++i) {
- if(oslots[i].entry <= UA_NODEMAP_TOMBSTONE)
- continue;
- UA_NodeMapSlot *s = findFreeSlot(ns, &oslots[i].entry->node.nodeId);
- UA_assert(s);
- *s = oslots[i];
- ++j;
+ UA_StatusCode retval = UA_copyCertificate (&context->remoteCertificate,
+ remoteCertificate);
+ if (retval != UA_STATUSCODE_GOOD) {
+ UA_free (context);
+ return retval;
}
- UA_free(oslots);
+ /* decode to X509 */
+ context->remoteCertificateX509 = UA_OpenSSL_LoadCertificate(&context->remoteCertificate);
+ if (context->remoteCertificateX509 == NULL) {
+ UA_ByteString_clear (&context->remoteCertificate);
+ UA_free (context);
+ return UA_STATUSCODE_BADCERTIFICATECHAININCOMPLETE;
+ }
+
+ context->policyContext = (Policy_Context_Basic256 *)
+ (securityPolicy->policyContext);
+
+ *channelContext = context;
+
+ UA_LOG_INFO (securityPolicy->logger,
+ UA_LOGCATEGORY_SECURITYPOLICY,
+ "The basic256 security policy channel with openssl is created.");
+
return UA_STATUSCODE_GOOD;
}
-static UA_NodeMapEntry *
-createEntry(UA_NodeClass nodeClass) {
- size_t size = sizeof(UA_NodeMapEntry) - sizeof(UA_Node);
- switch(nodeClass) {
- case UA_NODECLASS_OBJECT:
- size += sizeof(UA_ObjectNode);
- break;
- case UA_NODECLASS_VARIABLE:
- size += sizeof(UA_VariableNode);
- break;
- case UA_NODECLASS_METHOD:
- size += sizeof(UA_MethodNode);
- break;
- case UA_NODECLASS_OBJECTTYPE:
- size += sizeof(UA_ObjectTypeNode);
- break;
- case UA_NODECLASS_VARIABLETYPE:
- size += sizeof(UA_VariableTypeNode);
- break;
- case UA_NODECLASS_REFERENCETYPE:
- size += sizeof(UA_ReferenceTypeNode);
- break;
- case UA_NODECLASS_DATATYPE:
- size += sizeof(UA_DataTypeNode);
- break;
- case UA_NODECLASS_VIEW:
- size += sizeof(UA_ViewNode);
- break;
- default:
- return NULL;
+/* delete the channel context */
+
+static void
+UA_ChannelModule_Basic256_Delete_Context (void * channelContext) {
+ if (channelContext != NULL) {
+ Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *)
+ channelContext;
+ X509_free (cc->remoteCertificateX509);
+ UA_ByteString_clear (&cc->remoteCertificate);
+ UA_ByteString_clear (&cc->localSymSigningKey);
+ UA_ByteString_clear (&cc->localSymEncryptingKey);
+ UA_ByteString_clear (&cc->localSymIv);
+ UA_ByteString_clear (&cc->remoteSymSigningKey);
+ UA_ByteString_clear (&cc->remoteSymEncryptingKey);
+ UA_ByteString_clear (&cc->remoteSymIv);
+ UA_LOG_INFO (cc->policyContext->logger,
+ UA_LOGCATEGORY_SECURITYPOLICY,
+ "The basic256 security policy channel with openssl is deleted.");
+
+ UA_free (cc);
}
- UA_NodeMapEntry *entry = (UA_NodeMapEntry*)UA_calloc(1, size);
- if(!entry)
- return NULL;
- entry->node.nodeClass = nodeClass;
- return entry;
}
-static void
-deleteNodeMapEntry(UA_NodeMapEntry *entry) {
- UA_Node_clear(&entry->node);
- UA_free(entry);
-}
+/* Compares the supplied certificate with the certificate
+ * in the endpoint context
+ */
-static void
-cleanupNodeMapEntry(UA_NodeMapEntry *entry) {
- if(entry->deleted && entry->refCount == 0)
- deleteNodeMapEntry(entry);
+static UA_StatusCode
+UA_Asy_Basic256_compareCertificateThumbprint (const UA_SecurityPolicy * securityPolicy,
+ const UA_ByteString * certificateThumbprint) {
+ if (securityPolicy == NULL || certificateThumbprint == NULL) {
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+ }
+ Policy_Context_Basic256 *pc = (Policy_Context_Basic256 *)
+ securityPolicy->policyContext;
+ if(!UA_ByteString_equal(certificateThumbprint, &pc->localCertThumbprint)) {
+ return UA_STATUSCODE_BADCERTIFICATEINVALID;
+ }
+ return UA_STATUSCODE_GOOD;
}
-static UA_NodeMapSlot *
-findOccupiedSlot(const UA_NodeMap *ns, const UA_NodeId *nodeid) {
- UA_UInt32 h = UA_NodeId_hash(nodeid);
- UA_UInt32 size = ns->size;
- UA_UInt64 idx = mod(h, size); /* Use 64bit container to avoid overflow */
- UA_UInt32 hash2 = mod2(h, size);
- UA_UInt32 startIdx = (UA_UInt32)idx;
+/* Generates a thumbprint for the specified certificate */
- do {
- UA_NodeMapSlot *slot= &ns->slots[(UA_UInt32)idx];
- if(slot->entry > UA_NODEMAP_TOMBSTONE) {
- if(slot->nodeIdHash == h &&
- UA_NodeId_equal(&slot->entry->node.nodeId, nodeid))
- return slot;
- } else {
- if(slot->entry == NULL)
- return NULL; /* No further entry possible */
- }
+static UA_StatusCode
+UA_Asy_Basic256_makeCertificateThumbprint (const UA_SecurityPolicy * securityPolicy,
+ const UA_ByteString * certificate,
+ UA_ByteString * thumbprint) {
+ return UA_Openssl_X509_GetCertificateThumbprint (certificate,
+ thumbprint, false);
+}
- idx += hash2;
- if(idx >= size)
- idx -= size;
- } while((UA_UInt32)idx != startIdx);
+static UA_StatusCode
+UA_ChannelModule_Basic256_setLocalSymSigningKey (void * channelContext,
+ const UA_ByteString * key) {
+ if (key == NULL || channelContext == NULL) {
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+ }
- return NULL;
+ Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *) channelContext;
+ UA_ByteString_clear(&cc->localSymSigningKey);
+ return UA_ByteString_copy(key, &cc->localSymSigningKey);
}
-/***********************/
-/* Interface functions */
-/***********************/
+static UA_StatusCode
+UA_ChannelModule_Basic256_setLocalSymEncryptingKey (void * channelContext,
+ const UA_ByteString * key) {
+ if (key == NULL || channelContext == NULL) {
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+ }
-static UA_Node *
-UA_NodeMap_newNode(void *context, UA_NodeClass nodeClass) {
- UA_NodeMapEntry *entry = createEntry(nodeClass);
- if(!entry)
- return NULL;
- return &entry->node;
+ Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *) channelContext;
+ UA_ByteString_clear(&cc->localSymEncryptingKey);
+ return UA_ByteString_copy(key, &cc->localSymEncryptingKey);
}
-static void
-UA_NodeMap_deleteNode(void *context, UA_Node *node) {
- UA_NodeMapEntry *entry = container_of(node, UA_NodeMapEntry, node);
- UA_assert(&entry->node == node);
- deleteNodeMapEntry(entry);
-}
+static UA_StatusCode
+UA_ChannelModule_Basic256_setLocalSymIv (void * channelContext,
+ const UA_ByteString * iv) {
+ if (iv == NULL || channelContext == NULL) {
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+ }
-static const UA_Node *
-UA_NodeMap_getNode(void *context, const UA_NodeId *nodeid) {
- UA_NodeMap *ns = (UA_NodeMap*)context;
- UA_NodeMapSlot *slot = findOccupiedSlot(ns, nodeid);
- if(!slot)
- return NULL;
- ++slot->entry->refCount;
- return &slot->entry->node;
+ Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *) channelContext;
+ UA_ByteString_clear(&cc->localSymIv);
+ return UA_ByteString_copy(iv, &cc->localSymIv);
}
-static void
-UA_NodeMap_releaseNode(void *context, const UA_Node *node) {
- if (!node)
- return;
- UA_NodeMapEntry *entry = container_of(node, UA_NodeMapEntry, node);
- UA_assert(&entry->node == node);
- UA_assert(entry->refCount > 0);
- --entry->refCount;
- cleanupNodeMapEntry(entry);
+static UA_StatusCode
+UA_ChannelModule_Basic256_setRemoteSymSigningKey (void * channelContext,
+ const UA_ByteString * key) {
+ if (key == NULL || channelContext == NULL) {
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+ }
+
+ Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *) channelContext;
+ UA_ByteString_clear(&cc->remoteSymSigningKey);
+ return UA_ByteString_copy(key, &cc->remoteSymSigningKey);
}
static UA_StatusCode
-UA_NodeMap_getNodeCopy(void *context, const UA_NodeId *nodeid,
- UA_Node **outNode) {
- UA_NodeMap *ns = (UA_NodeMap*)context;
- UA_NodeMapSlot *slot = findOccupiedSlot(ns, nodeid);
- if(!slot)
- return UA_STATUSCODE_BADNODEIDUNKNOWN;
- UA_NodeMapEntry *entry = slot->entry;
- UA_NodeMapEntry *newItem = createEntry(entry->node.nodeClass);
- if(!newItem)
- return UA_STATUSCODE_BADOUTOFMEMORY;
- UA_StatusCode retval = UA_Node_copy(&entry->node, &newItem->node);
- if(retval == UA_STATUSCODE_GOOD) {
- newItem->orig = entry; /* Store the pointer to the original */
- *outNode = &newItem->node;
- } else {
- deleteNodeMapEntry(newItem);
+UA_ChannelModule_Basic256_setRemoteSymEncryptingKey (void * channelContext,
+ const UA_ByteString * key) {
+ if (key == NULL || channelContext == NULL) {
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
}
- return retval;
+
+ Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *) channelContext;
+ UA_ByteString_clear(&cc->remoteSymEncryptingKey);
+ return UA_ByteString_copy(key, &cc->remoteSymEncryptingKey);
}
static UA_StatusCode
-UA_NodeMap_removeNode(void *context, const UA_NodeId *nodeid) {
- UA_NodeMap *ns = (UA_NodeMap*)context;
- UA_NodeMapSlot *slot = findOccupiedSlot(ns, nodeid);
- if(!slot)
- return UA_STATUSCODE_BADNODEIDUNKNOWN;
+UA_ChannelModule_Basic256_setRemoteSymIv (void * channelContext,
+ const UA_ByteString * key) {
+ if (key == NULL || channelContext == NULL) {
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+ }
- UA_NodeMapEntry *entry = slot->entry;
- slot->entry = UA_NODEMAP_TOMBSTONE;
- UA_atomic_sync(); /* Set the tombstone before cleaning up. E.g. if the
- * nodestore is accessed from an interrupt. */
- entry->deleted = true;
- cleanupNodeMapEntry(entry);
- --ns->count;
- /* Downsize the hashmap if it is very empty */
- if(ns->count * 8 < ns->size && ns->size > UA_NODEMAP_MINSIZE)
- expand(ns); /* Can fail. Just continue with the bigger hashmap. */
- return UA_STATUSCODE_GOOD;
+ Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *) channelContext;
+ UA_ByteString_clear(&cc->remoteSymIv);
+ return UA_ByteString_copy(key, &cc->remoteSymIv);
}
static UA_StatusCode
-UA_NodeMap_insertNode(void *context, UA_Node *node,
- UA_NodeId *addedNodeId) {
- UA_NodeMap *ns = (UA_NodeMap*)context;
- if(ns->size * 3 <= ns->count * 4) {
- if(expand(ns) != UA_STATUSCODE_GOOD)
- return UA_STATUSCODE_BADINTERNALERROR;
+UA_ChannelModule_Basic256_compareCertificate (const void * channelContext,
+ const UA_ByteString * certificate) {
+ if(channelContext == NULL || certificate == NULL) {
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
}
- UA_NodeMapSlot *slot;
- if(node->nodeId.identifierType == UA_NODEIDTYPE_NUMERIC &&
- node->nodeId.identifier.numeric == 0) {
- /* Create a random nodeid: Start at least with 50,000 to make sure we
- * don not conflict with nodes from the spec. If we find a conflict, we
- * just try another identifier until we have tried all possible
- * identifiers. Since the size is prime and we don't change the increase
- * val, we will reach the starting id again. E.g. adding a nodeset will
- * create children while there are still other nodes which need to be
- * created. Thus the node ids may collide. */
- UA_UInt32 size = ns->size;
- UA_UInt64 identifier = mod(50000 + size+1, UA_UINT32_MAX); /* Use 64bit to
- * avoid overflow */
- UA_UInt32 increase = mod2(ns->count+1, size);
- UA_UInt32 startId = (UA_UInt32)identifier; /* mod ensures us that the id
- * is a valid 32 bit integer */
+ const Channel_Context_Basic256 * cc =
+ (const Channel_Context_Basic256 *) channelContext;
+ return UA_OpenSSL_X509_compare (certificate, cc->remoteCertificateX509);
+}
- do {
- node->nodeId.identifier.numeric = (UA_UInt32)identifier;
- slot = findFreeSlot(ns, &node->nodeId);
- if(slot)
- break;
- identifier += increase;
- if(identifier >= size)
- identifier -= size;
- } while((UA_UInt32)identifier != startId);
- } else {
- slot = findFreeSlot(ns, &node->nodeId);
+static size_t
+UA_AsySig_Basic256_getRemoteSignatureSize (const void *channelContext) {
+ if (channelContext == NULL) {
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
}
- if(!slot) {
- deleteNodeMapEntry(container_of(node, UA_NodeMapEntry, node));
- return UA_STATUSCODE_BADNODEIDEXISTS;
+ const Channel_Context_Basic256 * cc = (const Channel_Context_Basic256 *) channelContext;
+ UA_Int32 keyLen = 0;
+ UA_Openssl_RSA_Public_GetKeyLength (cc->remoteCertificateX509, &keyLen);
+ return (size_t) keyLen;
+}
+
+static size_t
+UA_AsySig_Basic256_getLocalSignatureSize (const void *channelContext) {
+ if (channelContext == NULL) {
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
}
- /* Copy the NodeId */
- UA_StatusCode retval = UA_STATUSCODE_GOOD;
- if(addedNodeId) {
- retval = UA_NodeId_copy(&node->nodeId, addedNodeId);
- if(retval != UA_STATUSCODE_GOOD) {
- deleteNodeMapEntry(container_of(node, UA_NodeMapEntry, node));
- return retval;
+ const Channel_Context_Basic256 * cc = (const Channel_Context_Basic256 *) channelContext;
+ Policy_Context_Basic256 * pc = cc->policyContext;
+ UA_Int32 keyLen = 0;
+ UA_Openssl_RSA_Private_GetKeyLength (pc->localPrivateKey, &keyLen);
+
+ return (size_t) keyLen;
+}
+
+static UA_StatusCode
+UA_AsySig_Basic256_Verify (void * channelContext,
+ const UA_ByteString * message,
+ const UA_ByteString * signature) {
+ if (message == NULL || signature == NULL || channelContext == NULL) {
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
}
- }
- /* Insert the node */
- UA_NodeMapEntry *newEntry = container_of(node, UA_NodeMapEntry, node);
- slot->nodeIdHash = UA_NodeId_hash(&node->nodeId);
- UA_atomic_sync(); /* Set the hash first */
- slot->entry = newEntry;
- ++ns->count;
+ Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *) channelContext;
+ UA_StatusCode retval = UA_OpenSSL_RSA_PKCS1_V15_SHA1_Verify (message,
+ cc->remoteCertificateX509, signature);
return retval;
}
static UA_StatusCode
-UA_NodeMap_replaceNode(void *context, UA_Node *node) {
- UA_NodeMap *ns = (UA_NodeMap*)context;
- UA_NodeMapEntry *newEntry = container_of(node, UA_NodeMapEntry, node);
-
- /* Find the node */
- UA_NodeMapSlot *slot = findOccupiedSlot(ns, &node->nodeId);
- if(!slot) {
- deleteNodeMapEntry(newEntry);
- return UA_STATUSCODE_BADNODEIDUNKNOWN;
+UA_AsySig_Basic256_Sign (void * channelContext,
+ const UA_ByteString * message,
+ UA_ByteString * signature) {
+ if (channelContext == NULL || message == NULL || signature == NULL) {
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
}
- /* The node was already updated since the copy was made? */
- UA_NodeMapEntry *oldEntry = slot->entry;
- if(oldEntry != newEntry->orig) {
- deleteNodeMapEntry(newEntry);
- return UA_STATUSCODE_BADINTERNALERROR;
+ Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *) channelContext;
+ Policy_Context_Basic256 * pc = cc->policyContext;
+ return UA_Openssl_RSA_PKCS1_V15_SHA1_Sign (message, pc->localPrivateKey,
+ signature);
+}
+
+static size_t
+UA_AsymEn_Basic256_getRemotePlainTextBlockSize (const void *channelContext) {
+ if (channelContext == NULL) {
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
}
- /* Replace the entry */
- slot->entry = newEntry;
- UA_atomic_sync();
- oldEntry->deleted = true;
- cleanupNodeMapEntry(oldEntry);
- return UA_STATUSCODE_GOOD;
+ const Channel_Context_Basic256 * cc = (const Channel_Context_Basic256 *) channelContext;
+ UA_Int32 keyLen = 0;
+ UA_Openssl_RSA_Public_GetKeyLength (cc->remoteCertificateX509, &keyLen);
+ return (size_t) keyLen - UA_SECURITYPOLICY_BASIC256SHA1_RSAPADDING_LEN;
}
-static void
-UA_NodeMap_iterate(void *context, UA_NodestoreVisitor visitor,
- void *visitorContext) {
- UA_NodeMap *ns = (UA_NodeMap*)context;
- for(UA_UInt32 i = 0; i < ns->size; ++i) {
- UA_NodeMapSlot *slot = &ns->slots[i];
- if(slot->entry > UA_NODEMAP_TOMBSTONE) {
- /* The visitor can delete the node. So refcount here. */
- slot->entry->refCount++;
- visitor(visitorContext, &slot->entry->node);
- slot->entry->refCount--;
- cleanupNodeMapEntry(slot->entry);
- }
+static size_t
+UA_AsymEn_Basic256_getRemoteBlockSize (const void *channelContext) {
+ if (channelContext == NULL) {
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
}
+
+ const Channel_Context_Basic256 * cc = (const Channel_Context_Basic256 *) channelContext;
+ UA_Int32 keyLen = 0;
+ UA_Openssl_RSA_Public_GetKeyLength (cc->remoteCertificateX509, &keyLen);
+ return (size_t) keyLen;
}
-static void
-UA_NodeMap_delete(void *context) {
- UA_NodeMap *ns = (UA_NodeMap*)context;
- UA_UInt32 size = ns->size;
- UA_NodeMapSlot *slots = ns->slots;
- for(UA_UInt32 i = 0; i < size; ++i) {
- if(slots[i].entry > UA_NODEMAP_TOMBSTONE) {
- /* On debugging builds, check that all nodes were release */
- UA_assert(slots[i].entry->refCount == 0);
- /* Delete the node */
- deleteNodeMapEntry(slots[i].entry);
- }
- }
- UA_free(ns->slots);
- UA_free(ns);
+static size_t
+UA_AsymEn_Basic256_getRemoteKeyLength (const void *channelContext) {
+ if (channelContext == NULL)
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+
+ const Channel_Context_Basic256 * cc = (const Channel_Context_Basic256 *) channelContext;
+ UA_Int32 keyLen = 0;
+ UA_Openssl_RSA_Public_GetKeyLength (cc->remoteCertificateX509, &keyLen);
+ return (size_t) keyLen * 8;
}
-UA_StatusCode
-UA_Nodestore_HashMap(UA_Nodestore *ns) {
- /* Allocate and initialize the nodemap */
- UA_NodeMap *nodemap = (UA_NodeMap*)UA_malloc(sizeof(UA_NodeMap));
- if(!nodemap)
- return UA_STATUSCODE_BADOUTOFMEMORY;
- nodemap->sizePrimeIndex = higher_prime_index(UA_NODEMAP_MINSIZE);
- nodemap->size = primes[nodemap->sizePrimeIndex];
- nodemap->count = 0;
- nodemap->slots = (UA_NodeMapSlot*)
- UA_calloc(nodemap->size, sizeof(UA_NodeMapSlot));
- if(!nodemap->slots) {
- UA_free(nodemap);
- return UA_STATUSCODE_BADOUTOFMEMORY;
+static size_t
+UA_AsymEn_Basic256_getLocalKeyLength (const void *channelContext) {
+ if (channelContext == NULL)
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+
+ const Channel_Context_Basic256 *cc = (const Channel_Context_Basic256 *) channelContext;
+ Policy_Context_Basic256 *pc = cc->policyContext;
+ UA_Int32 keyLen = 0;
+ UA_Openssl_RSA_Private_GetKeyLength (pc->localPrivateKey, &keyLen);
+
+ return (size_t) keyLen * 8;
+}
+
+static UA_StatusCode
+UA_AsymEn_Basic256_Decrypt (void * channelContext,
+ UA_ByteString * data) {
+ if (channelContext == NULL || data == NULL) {
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
}
- /* Populate the nodestore */
- ns->context = nodemap;
- ns->clear = UA_NodeMap_delete;
- ns->newNode = UA_NodeMap_newNode;
- ns->deleteNode = UA_NodeMap_deleteNode;
- ns->getNode = UA_NodeMap_getNode;
- ns->releaseNode = UA_NodeMap_releaseNode;
- ns->getNodeCopy = UA_NodeMap_getNodeCopy;
- ns->insertNode = UA_NodeMap_insertNode;
- ns->replaceNode = UA_NodeMap_replaceNode;
- ns->removeNode = UA_NodeMap_removeNode;
- ns->iterate = UA_NodeMap_iterate;
- return UA_STATUSCODE_GOOD;
+ Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *) channelContext;
+ UA_StatusCode ret = UA_Openssl_RSA_Oaep_Decrypt (data,
+ cc->policyContext->localPrivateKey);
+ return ret;
}
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/plugins/ua_config_default.c" ***********************************/
+static UA_StatusCode
+UA_AsymEn_Basic256_Encrypt (void * channelContext,
+ UA_ByteString * data) {
+ if (channelContext == NULL || data == NULL) {
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+ }
-/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
- * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
- *
- * Copyright 2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
- * Copyright 2017 (c) Julian Grothoff
- * Copyright 2017-2018 (c) Mark Giraud, Fraunhofer IOSB
- * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
- * Copyright 2017 (c) Thomas Stalder, Blue Time Concept SA
- * Copyright 2018 (c) Daniel Feist, Precitec GmbH & Co. KG
- * Copyright 2018 (c) Fabian Arndt, Root-Core
- * Copyright 2019 (c) Kalycito Infotech Private Limited
- * Copyright 2017-2020 (c) HMS Industrial Networks AB (Author: Jonas Green)
- * Copyright 2020 (c) Wind River Systems, Inc.
- */
+ Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *) channelContext;
+ return UA_Openssl_RSA_OAEP_Encrypt (data, UA_SECURITYPOLICY_BASIC256SHA1_RSAPADDING_LEN,
+ cc->remoteCertificateX509);
+}
-#ifdef UA_ENABLE_WEBSOCKET_SERVER
-#endif
+static UA_StatusCode
+UA_Sym_Basic256_generateNonce(void *policyContext,
+ UA_ByteString *out) {
+ UA_Int32 rc = RAND_bytes(out->data, (int) out->length);
+ if (rc != 1) {
+ return UA_STATUSCODE_BADUNEXPECTEDERROR;
+ }
+ return UA_STATUSCODE_GOOD;
+}
-/* Struct initialization works across ANSI C/C99/C++ if it is done when the
- * variable is first declared. Assigning values to existing structs is
- * heterogeneous across the three. */
-static UA_INLINE UA_UInt32Range
-UA_UINT32RANGE(UA_UInt32 min, UA_UInt32 max) {
- UA_UInt32Range range = {min, max};
- return range;
+static UA_StatusCode
+UA_Sym_Basic256_generateKey(void *policyContext, const UA_ByteString *secret,
+ const UA_ByteString *seed, UA_ByteString *out) {
+ return UA_Openssl_Random_Key_PSHA1_Derive(secret, seed, out);
}
-static UA_INLINE UA_DurationRange
-UA_DURATIONRANGE(UA_Duration min, UA_Duration max) {
- UA_DurationRange range = {min, max};
- return range;
+static size_t
+UA_SymEn_Basic256_getLocalKeyLength (const void * channelContext) {
+ /* 32 bytes 256 bits */
+ return UA_SECURITYPOLICY_BASIC256_SYM_ENCRYPTION_KEY_LENGTH;
}
-UA_Server *
-UA_Server_new() {
- UA_ServerConfig config;
- memset(&config, 0, sizeof(UA_ServerConfig));
- /* Set a default logger and NodeStore for the initialization */
- config.logger = UA_Log_Stdout_;
- UA_Nodestore_HashMap(&config.nodestore);
- return UA_Server_newWithConfig(&config);
+static size_t
+UA_SymEn_Basic256_getBlockSize (const void * channelContext) {
+ return UA_SECURITYPOLICY_BASIC256_SYM_ENCRYPTION_BLOCK_SIZE;
}
-/*******************************/
-/* Default Connection Settings */
-/*******************************/
+static size_t
+UA_SymEn_Basic256_getRemoteKeyLength (const void * channelContext) {
+ /* 32 bytes 256 bits */
+ return UA_SECURITYPOLICY_BASIC256_SYM_ENCRYPTION_KEY_LENGTH;
+}
-const UA_ConnectionConfig UA_ConnectionConfig_default = {
- 0, /* .protocolVersion */
- 65535, /* .sendBufferSize, 64k per chunk */
- 65535, /* .recvBufferSize, 64k per chunk */
- 0, /* .localMaxMessageSize, 0 -> unlimited */
- 0, /* .remoteMaxMessageSize, 0 -> unlimited */
- 0, /* .localMaxChunkCount, 0 -> unlimited */
- 0 /* .remoteMaxChunkCount, 0 -> unlimited */
-};
+static UA_StatusCode
+UA_SymEn_Basic256_Encrypt (void * channelContext,
+ UA_ByteString * data) {
+ if(channelContext == NULL || data == NULL)
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+
+ Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *) channelContext;
+ return UA_OpenSSL_AES_256_CBC_Encrypt (&cc->localSymIv, &cc->localSymEncryptingKey, data);
+}
-/***************************/
-/* Default Server Settings */
-/***************************/
+static UA_StatusCode
+UA_SymEn_Basic256_Decrypt (void * channelContext,
+ UA_ByteString * data) {
+ if(channelContext == NULL || data == NULL)
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+ Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *) channelContext;
+ return UA_OpenSSL_AES_256_CBC_Decrypt (&cc->remoteSymIv, &cc->remoteSymEncryptingKey, data);
+}
-#define MANUFACTURER_NAME "open62541"
-#define PRODUCT_NAME "open62541 OPC UA Server"
-#define PRODUCT_URI "http://open62541.org"
-#define APPLICATION_NAME "open62541-based OPC UA Application"
-#define APPLICATION_URI "urn:unconfigured:application"
-#define APPLICATION_URI_SERVER "urn:open62541.server.application"
+static size_t
+UA_SymSig_Basic256_getKeyLength (const void * channelContext) {
+ return UA_SECURITYPOLICY_BASIC256_SYM_SIGNING_KEY_LENGTH;
+}
-#define STRINGIFY(arg) #arg
-#define VERSION(MAJOR, MINOR, PATCH, LABEL) \
- STRINGIFY(MAJOR) "." STRINGIFY(MINOR) "." STRINGIFY(PATCH) LABEL
+static size_t
+UA_SymSig_Basic256_getSignatureSize (const void * channelContext) {
+ return UA_SHA1_LENGTH;
+}
static UA_StatusCode
-createEndpoint(UA_ServerConfig *conf, UA_EndpointDescription *endpoint,
- const UA_SecurityPolicy *securityPolicy,
- UA_MessageSecurityMode securityMode) {
- UA_EndpointDescription_init(endpoint);
+UA_SymSig_Basic256_Verify (void * channelContext,
+ const UA_ByteString * message,
+ const UA_ByteString * signature) {
+ if (channelContext == NULL ||
+ message == NULL || signature == NULL)
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+
+ Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *) channelContext;
+ return UA_OpenSSL_HMAC_SHA1_Verify (message,
+ &cc->remoteSymSigningKey,
+ signature);
+}
- endpoint->securityMode = securityMode;
- UA_String_copy(&securityPolicy->policyUri, &endpoint->securityPolicyUri);
- endpoint->transportProfileUri =
- UA_STRING_ALLOC("http://opcfoundation.org/UA-Profile/Transport/uatcp-uasc-uabinary");
+static UA_StatusCode
+UA_SymSig_Basic256_Sign (void * channelContext,
+ const UA_ByteString * message,
+ UA_ByteString * signature) {
+ if (channelContext == NULL || message == NULL || signature == NULL)
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+
+ Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *) channelContext;
+ return UA_OpenSSL_HMAC_SHA1_Sign (message, &cc->localSymSigningKey, signature);
+}
- /* Add security level value for the corresponding message security mode */
- endpoint->securityLevel = (UA_Byte) securityMode;
+/* the main entry of Basic256 */
- /* Enable all login mechanisms from the access control plugin */
- UA_StatusCode retval = UA_Array_copy(conf->accessControl.userTokenPolicies,
- conf->accessControl.userTokenPoliciesSize,
- (void **)&endpoint->userIdentityTokens,
- &UA_TYPES[UA_TYPES_USERTOKENPOLICY]);
- if(retval != UA_STATUSCODE_GOOD)
- return retval;
- endpoint->userIdentityTokensSize = conf->accessControl.userTokenPoliciesSize;
+UA_StatusCode
+UA_SecurityPolicy_Basic256 (UA_SecurityPolicy * policy,
+ const UA_ByteString localCertificate,
+ const UA_ByteString localPrivateKey,
+ const UA_Logger * logger) {
+ UA_SecurityPolicyAsymmetricModule * const asymmetricModule = &policy->asymmetricModule;
+ UA_SecurityPolicySymmetricModule * const symmetricModule = &policy->symmetricModule;
+ UA_SecurityPolicyChannelModule * const channelModule = &policy->channelModule;
+ UA_StatusCode retval;
- UA_String_copy(&securityPolicy->localCertificate, &endpoint->serverCertificate);
- UA_ApplicationDescription_copy(&conf->applicationDescription, &endpoint->server);
+ UA_LOG_INFO (logger, UA_LOGCATEGORY_SECURITYPOLICY,
+ "The basic256 security policy with openssl is added.");
- return UA_STATUSCODE_GOOD;
-}
+ UA_Openssl_Init ();
+ memset(policy, 0, sizeof(UA_SecurityPolicy));
+ policy->logger = logger;
+ policy->policyUri = UA_STRING("http://opcfoundation.org/UA/SecurityPolicy#Basic256\0");
-static const size_t usernamePasswordsSize = 2;
-static UA_UsernamePasswordLogin usernamePasswords[2] = {
- {UA_STRING_STATIC("user1"), UA_STRING_STATIC("password")},
- {UA_STRING_STATIC("user2"), UA_STRING_STATIC("password1")}};
+ /* set ChannelModule context */
-static UA_StatusCode
-setDefaultConfig(UA_ServerConfig *conf) {
- if (!conf)
- return UA_STATUSCODE_BADINVALIDARGUMENT;
+ channelModule->newContext = UA_ChannelModule_Basic256_New_Context;
+ channelModule->deleteContext = UA_ChannelModule_Basic256_Delete_Context;
- if(conf->nodestore.context == NULL)
- UA_Nodestore_HashMap(&conf->nodestore);
+ channelModule->setLocalSymSigningKey = UA_ChannelModule_Basic256_setLocalSymSigningKey;
+ channelModule->setLocalSymEncryptingKey = UA_ChannelModule_Basic256_setLocalSymEncryptingKey;
+ channelModule->setLocalSymIv = UA_ChannelModule_Basic256_setLocalSymIv;
+ channelModule->setRemoteSymSigningKey = UA_ChannelModule_Basic256_setRemoteSymSigningKey;
+ channelModule->setRemoteSymEncryptingKey = UA_ChannelModule_Basic256_setRemoteSymEncryptingKey;
+ channelModule->setRemoteSymIv = UA_ChannelModule_Basic256_setRemoteSymIv;
+ channelModule->compareCertificate = UA_ChannelModule_Basic256_compareCertificate;
- /* --> Start setting the default static config <-- */
- conf->nThreads = 1;
+ retval = UA_OpenSSL_LoadLocalCertificate(&localCertificate, &policy->localCertificate);
- /* Allow user to set his own logger */
- if (!conf->logger.log)
- conf->logger = UA_Log_Stdout_;
+ if (retval != UA_STATUSCODE_GOOD)
+ return retval;
- conf->shutdownDelay = 0.0;
+ /* asymmetricModule */
- /* Server Description */
- UA_BuildInfo_clear(&conf->buildInfo);
- conf->buildInfo.productUri = UA_STRING_ALLOC(PRODUCT_URI);
- conf->buildInfo.manufacturerName = UA_STRING_ALLOC(MANUFACTURER_NAME);
- conf->buildInfo.productName = UA_STRING_ALLOC(PRODUCT_NAME);
- conf->buildInfo.softwareVersion =
- UA_STRING_ALLOC(VERSION(UA_OPEN62541_VER_MAJOR, UA_OPEN62541_VER_MINOR,
- UA_OPEN62541_VER_PATCH, UA_OPEN62541_VER_LABEL));
- #ifdef UA_PACK_DEBIAN
- conf->buildInfo.buildNumber = UA_STRING_ALLOC("deb");
- #else
- conf->buildInfo.buildNumber = UA_STRING_ALLOC(__DATE__ " " __TIME__);
- #endif
- conf->buildInfo.buildDate = UA_DateTime_now();
+ asymmetricModule->compareCertificateThumbprint = UA_Asy_Basic256_compareCertificateThumbprint;
+ asymmetricModule->makeCertificateThumbprint = UA_Asy_Basic256_makeCertificateThumbprint;
- UA_ApplicationDescription_clear(&conf->applicationDescription);
- conf->applicationDescription.applicationUri = UA_STRING_ALLOC(APPLICATION_URI_SERVER);
- conf->applicationDescription.productUri = UA_STRING_ALLOC(PRODUCT_URI);
- conf->applicationDescription.applicationName =
- UA_LOCALIZEDTEXT_ALLOC("en", APPLICATION_NAME);
- conf->applicationDescription.applicationType = UA_APPLICATIONTYPE_SERVER;
- /* conf->applicationDescription.gatewayServerUri = UA_STRING_NULL; */
- /* conf->applicationDescription.discoveryProfileUri = UA_STRING_NULL; */
- /* conf->applicationDescription.discoveryUrlsSize = 0; */
- /* conf->applicationDescription.discoveryUrls = NULL; */
+ /* AsymmetricModule - signature algorithm */
-#ifdef UA_ENABLE_DISCOVERY_MULTICAST
- UA_MdnsDiscoveryConfiguration_clear(&conf->discovery.mdns);
- conf->discovery.mdnsInterfaceIP = UA_STRING_NULL;
-# if !defined(UA_HAS_GETIFADDR)
- conf->discovery.ipAddressList = NULL;
- conf->discovery.ipAddressListSize = 0;
-# endif
-#endif
+ UA_SecurityPolicySignatureAlgorithm * asySigAlgorithm =
+ &asymmetricModule->cryptoModule.signatureAlgorithm;
+ asySigAlgorithm->uri = UA_STRING("http://www.w3.org/2000/09/xmldsig#rsa-sha1\0");
+ asySigAlgorithm->getRemoteSignatureSize = UA_AsySig_Basic256_getRemoteSignatureSize;
+ asySigAlgorithm->getLocalSignatureSize = UA_AsySig_Basic256_getLocalSignatureSize;
+ asySigAlgorithm->verify = UA_AsySig_Basic256_Verify;
+ asySigAlgorithm->sign = UA_AsySig_Basic256_Sign;
+ asySigAlgorithm->getLocalKeyLength = NULL;
+ asySigAlgorithm->getRemoteKeyLength = NULL;
- /* Custom DataTypes */
- /* conf->customDataTypesSize = 0; */
- /* conf->customDataTypes = NULL; */
+ /* AsymmetricModule encryption algorithm */
- /* Networking */
- /* conf->networkLayersSize = 0; */
- /* conf->networkLayers = NULL; */
- /* conf->customHostname = UA_STRING_NULL; */
+ UA_SecurityPolicyEncryptionAlgorithm * asymEncryAlg =
+ &asymmetricModule->cryptoModule.encryptionAlgorithm;
+ asymEncryAlg->uri = UA_STRING("http://www.w3.org/2001/04/xmlenc#rsa-oaep\0");
+ asymEncryAlg->getRemotePlainTextBlockSize = UA_AsymEn_Basic256_getRemotePlainTextBlockSize;
+ asymEncryAlg->getRemoteBlockSize = UA_AsymEn_Basic256_getRemoteBlockSize;
+ asymEncryAlg->getRemoteKeyLength = UA_AsymEn_Basic256_getRemoteKeyLength;
+ asymEncryAlg->getLocalKeyLength = UA_AsymEn_Basic256_getLocalKeyLength;
+ asymEncryAlg->decrypt = UA_AsymEn_Basic256_Decrypt;
+ asymEncryAlg->encrypt = UA_AsymEn_Basic256_Encrypt;
- /* Endpoints */
- /* conf->endpoints = {0, NULL}; */
+ /* SymmetricModule */
- /* Certificate Verification that accepts every certificate. Can be
- * overwritten when the policy is specialized. */
- UA_CertificateVerification_AcceptAll(&conf->certificateVerification);
+ symmetricModule->secureChannelNonceLength = 32;
+ symmetricModule->generateNonce = UA_Sym_Basic256_generateNonce;
+ symmetricModule->generateKey = UA_Sym_Basic256_generateKey;
- /* * Global Node Lifecycle * */
- /* conf->nodeLifecycle.constructor = NULL; */
- /* conf->nodeLifecycle.destructor = NULL; */
- /* conf->nodeLifecycle.createOptionalChild = NULL; */
- /* conf->nodeLifecycle.generateChildNodeId = NULL; */
+ /* Symmetric encryption Algorithm */
- /* Relax constraints for the InformationModel */
- conf->relaxEmptyValueConstraint = true; /* Allow empty values */
+ UA_SecurityPolicyEncryptionAlgorithm * symEncryptionAlgorithm =
+ &symmetricModule->cryptoModule.encryptionAlgorithm;
+ symEncryptionAlgorithm->uri = UA_STRING("http://www.w3.org/2001/04/xmlenc#aes256-cbc\0");
+ symEncryptionAlgorithm->getLocalKeyLength = UA_SymEn_Basic256_getLocalKeyLength;
+ symEncryptionAlgorithm->getRemoteKeyLength = UA_SymEn_Basic256_getRemoteKeyLength;
+ symEncryptionAlgorithm->getRemoteBlockSize = UA_SymEn_Basic256_getBlockSize;
+ symEncryptionAlgorithm->getRemotePlainTextBlockSize = UA_SymEn_Basic256_getBlockSize;
+ symEncryptionAlgorithm->decrypt = UA_SymEn_Basic256_Decrypt;
+ symEncryptionAlgorithm->encrypt = UA_SymEn_Basic256_Encrypt;
- /* Limits for SecureChannels */
- conf->maxSecureChannels = 40;
- conf->maxSecurityTokenLifetime = 10 * 60 * 1000; /* 10 minutes */
+ /* Symmetric signature Algorithm */
- /* Limits for Sessions */
- conf->maxSessions = 100;
- conf->maxSessionTimeout = 60.0 * 60.0 * 1000.0; /* 1h */
+ UA_SecurityPolicySignatureAlgorithm * symSignatureAlgorithm =
+ &symmetricModule->cryptoModule.signatureAlgorithm;
+ symSignatureAlgorithm->uri = UA_STRING("http://www.w3.org/2000/09/xmldsig#hmac-sha1\0");
+ symSignatureAlgorithm->getLocalKeyLength = UA_SymSig_Basic256_getKeyLength;
+ symSignatureAlgorithm->getRemoteKeyLength = UA_SymSig_Basic256_getKeyLength;
+ symSignatureAlgorithm->getRemoteSignatureSize = UA_SymSig_Basic256_getSignatureSize;
+ symSignatureAlgorithm->getLocalSignatureSize = UA_SymSig_Basic256_getSignatureSize;
+ symSignatureAlgorithm->verify = UA_SymSig_Basic256_Verify;
+ symSignatureAlgorithm->sign = UA_SymSig_Basic256_Sign;
- /* Limits for Subscriptions */
- conf->publishingIntervalLimits = UA_DURATIONRANGE(100.0, 3600.0 * 1000.0);
- conf->lifeTimeCountLimits = UA_UINT32RANGE(3, 15000);
- conf->keepAliveCountLimits = UA_UINT32RANGE(1, 100);
- conf->maxNotificationsPerPublish = 1000;
- conf->enableRetransmissionQueue = true;
- conf->maxRetransmissionQueueSize = 0; /* unlimited */
-#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
- conf->maxEventsPerNode = 0; /* unlimited */
-#endif
+ /* set the policy context */
- /* Limits for MonitoredItems */
- conf->samplingIntervalLimits = UA_DURATIONRANGE(50.0, 24.0 * 3600.0 * 1000.0);
- conf->queueSizeLimits = UA_UINT32RANGE(1, 100);
+ retval = UA_Policy_Basic256_New_Context (policy, localPrivateKey, logger);
+ if (retval != UA_STATUSCODE_GOOD) {
+ UA_ByteString_clear (&policy->localCertificate);
+ return retval;
+ }
+ policy->clear = UA_Policy_Basic256_Clear_Context;
+
+ /* Use the same signature algorithm as the asymmetric component for
+ certificate signing (see standard) */
+ policy->certificateSigningAlgorithm = policy->asymmetricModule.cryptoModule.signatureAlgorithm;
+
+ return UA_STATUSCODE_GOOD;
+}
-#ifdef UA_ENABLE_DISCOVERY
- conf->discovery.cleanupTimeout = 60 * 60;
#endif
-#ifdef UA_ENABLE_HISTORIZING
- /* conf->accessHistoryDataCapability = UA_FALSE; */
- /* conf->maxReturnDataValues = 0; */
+/**** amalgamated original file "/plugins/crypto/openssl/ua_openssl_basic256sha256.c" ****/
- /* conf->accessHistoryEventsCapability = UA_FALSE; */
- /* conf->maxReturnEventValues = 0; */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Copyright 2020 (c) Wind River Systems, Inc.
+ * Copyright 2020 (c) basysKom GmbH
+ */
- /* conf->insertDataCapability = UA_FALSE; */
- /* conf->insertEventCapability = UA_FALSE; */
- /* conf->insertAnnotationsCapability = UA_FALSE; */
- /* conf->replaceDataCapability = UA_FALSE; */
- /* conf->replaceEventCapability = UA_FALSE; */
+#if defined(UA_ENABLE_ENCRYPTION_OPENSSL) || defined(UA_ENABLE_ENCRYPTION_LIBRESSL)
- /* conf->updateDataCapability = UA_FALSE; */
- /* conf->updateEventCapability = UA_FALSE; */
- /* conf->deleteRawCapability = UA_FALSE; */
- /* conf->deleteEventCapability = UA_FALSE; */
- /* conf->deleteAtTimeDataCapability = UA_FALSE; */
-#endif
+#include <openssl/hmac.h>
+#include <openssl/sha.h>
+#include <openssl/rsa.h>
+#include <openssl/x509.h>
+#include <openssl/rand.h>
+#include <openssl/rsa.h>
-#if UA_MULTITHREADING >= 100
- conf->maxAsyncOperationQueueSize = 0;
- conf->asyncOperationTimeout = 120000; /* Async Operation Timeout in ms (2 minutes) */
-#endif
+#define UA_SHA256_LENGTH 32 /* 256 bit */
+#define UA_SECURITYPOLICY_BASIC256SHA256_RSAPADDING_LEN 42
+#define UA_SECURITYPOLICY_BASIC256SHA256_SYM_SIGNING_KEY_LENGTH 32
+#define UA_SECURITYPOLICY_BASIC256SHA256_SYM_ENCRYPTION_KEY_LENGTH 32
+#define UA_SECURITYPOLICY_BASIC256SHA256_SYM_ENCRYPTION_BLOCK_SIZE 16
+#define UA_SECURITYPOLICY_BASIC256SHA256_SYM_PLAIN_TEXT_BLOCK_SIZE 16
+#define UA_SECURITYPOLICY_BASIC256SHA256_MINASYMKEYLENGTH 256
+#define UA_SECURITYPOLICY_BASIC256SHA256_MAXASYMKEYLENGTH 512
- /* --> Finish setting the default static config <-- */
+typedef struct {
+ EVP_PKEY *localPrivateKey;
+ UA_ByteString localCertThumbprint;
+ const UA_Logger *logger;
+} Policy_Context_Basic256Sha256;
- return UA_STATUSCODE_GOOD;
-}
+typedef struct {
+ UA_ByteString localSymSigningKey;
+ UA_ByteString localSymEncryptingKey;
+ UA_ByteString localSymIv;
+ UA_ByteString remoteSymSigningKey;
+ UA_ByteString remoteSymEncryptingKey;
+ UA_ByteString remoteSymIv;
-UA_EXPORT UA_StatusCode
-UA_ServerConfig_setBasics(UA_ServerConfig* conf) {
- UA_StatusCode res = setDefaultConfig(conf);
- UA_LOG_WARNING(&conf->logger, UA_LOGCATEGORY_USERLAND,
- "AcceptAll Certificate Verification. "
- "Any remote certificate will be accepted.");
- return res;
-}
+ Policy_Context_Basic256Sha256 *policyContext;
+ UA_ByteString remoteCertificate;
+ X509 *remoteCertificateX509; /* X509 */
+} Channel_Context_Basic256Sha256;
-static UA_StatusCode
-addDefaultNetworkLayers(UA_ServerConfig *conf, UA_UInt16 portNumber,
- UA_UInt32 sendBufferSize, UA_UInt32 recvBufferSize) {
- return UA_ServerConfig_addNetworkLayerTCP(conf, portNumber, sendBufferSize, recvBufferSize);
-}
+/* create the policy context */
-#ifdef UA_ENABLE_WEBSOCKET_SERVER
-UA_EXPORT UA_StatusCode
-UA_ServerConfig_addNetworkLayerWS(UA_ServerConfig *conf, UA_UInt16 portNumber,
- UA_UInt32 sendBufferSize, UA_UInt32 recvBufferSize) {
- /* Add a network layer */
- UA_ServerNetworkLayer *tmp = (UA_ServerNetworkLayer *)
- UA_realloc(conf->networkLayers,
- sizeof(UA_ServerNetworkLayer) * (1 + conf->networkLayersSize));
- if(!tmp)
+static UA_StatusCode
+UA_Policy_New_Context(UA_SecurityPolicy * securityPolicy,
+ const UA_ByteString localPrivateKey,
+ const UA_Logger *logger) {
+ Policy_Context_Basic256Sha256 *context = (Policy_Context_Basic256Sha256 *)
+ UA_malloc(sizeof(Policy_Context_Basic256Sha256));
+ if(context == NULL)
return UA_STATUSCODE_BADOUTOFMEMORY;
- conf->networkLayers = tmp;
+ context->localPrivateKey = UA_OpenSSL_LoadPrivateKey(&localPrivateKey);
- UA_ConnectionConfig config = UA_ConnectionConfig_default;
- if (sendBufferSize > 0)
- config.sendBufferSize = sendBufferSize;
- if (recvBufferSize > 0)
- config.recvBufferSize = recvBufferSize;
+ if(!context->localPrivateKey) {
+ UA_free(context);
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+ }
- conf->networkLayers[conf->networkLayersSize] =
- UA_ServerNetworkLayerWS(config, portNumber, &conf->logger);
- if (!conf->networkLayers[conf->networkLayersSize].handle)
- return UA_STATUSCODE_BADOUTOFMEMORY;
- conf->networkLayersSize++;
+ UA_StatusCode retval =
+ UA_Openssl_X509_GetCertificateThumbprint(&securityPolicy->localCertificate,
+ &context->localCertThumbprint, true);
+ if(retval != UA_STATUSCODE_GOOD) {
+ EVP_PKEY_free(context->localPrivateKey);
+ UA_free(context);
+ return retval;
+ }
+ context->logger = logger;
+ securityPolicy->policyContext = context;
return UA_STATUSCODE_GOOD;
}
-#endif
-UA_EXPORT UA_StatusCode
-UA_ServerConfig_addNetworkLayerTCP(UA_ServerConfig *conf, UA_UInt16 portNumber,
- UA_UInt32 sendBufferSize, UA_UInt32 recvBufferSize) {
- /* Add a network layer */
- UA_ServerNetworkLayer *tmp = (UA_ServerNetworkLayer *)
- UA_realloc(conf->networkLayers,
- sizeof(UA_ServerNetworkLayer) * (1 + conf->networkLayersSize));
- if(!tmp)
- return UA_STATUSCODE_BADOUTOFMEMORY;
- conf->networkLayers = tmp;
-
- UA_ConnectionConfig config = UA_ConnectionConfig_default;
- if (sendBufferSize > 0)
- config.sendBufferSize = sendBufferSize;
- if (recvBufferSize > 0)
- config.recvBufferSize = recvBufferSize;
+/* Clear the policy context */
+static void
+UA_Policy_Clear_Context(UA_SecurityPolicy *policy) {
+ if(policy == NULL)
+ return;
- conf->networkLayers[conf->networkLayersSize] =
- UA_ServerNetworkLayerTCP(config, portNumber, 0, &conf->logger);
- if (!conf->networkLayers[conf->networkLayersSize].handle)
- return UA_STATUSCODE_BADOUTOFMEMORY;
- conf->networkLayersSize++;
+ UA_ByteString_clear(&policy->localCertificate);
- return UA_STATUSCODE_GOOD;
+ /* Delete all allocated members in the context */
+ Policy_Context_Basic256Sha256 *pc =
+ (Policy_Context_Basic256Sha256 *) policy->policyContext;
+ EVP_PKEY_free(pc->localPrivateKey);
+ UA_ByteString_clear(&pc->localCertThumbprint);
+ UA_free(pc);
+ return;
}
-UA_EXPORT UA_StatusCode
-UA_ServerConfig_addSecurityPolicyNone(UA_ServerConfig *config,
- const UA_ByteString *certificate) {
- /* Allocate the SecurityPolicies */
- UA_SecurityPolicy *tmp = (UA_SecurityPolicy *)
- UA_realloc(config->securityPolicies,
- sizeof(UA_SecurityPolicy) * (1 + config->securityPoliciesSize));
- if(!tmp)
+/* create the channel context */
+
+static UA_StatusCode
+UA_ChannelModule_New_Context(const UA_SecurityPolicy * securityPolicy,
+ const UA_ByteString * remoteCertificate,
+ void ** channelContext) {
+ if(securityPolicy == NULL || remoteCertificate == NULL || channelContext == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ Channel_Context_Basic256Sha256 *context = (Channel_Context_Basic256Sha256 *)
+ UA_malloc(sizeof(Channel_Context_Basic256Sha256));
+ if(context == NULL)
return UA_STATUSCODE_BADOUTOFMEMORY;
- config->securityPolicies = tmp;
-
- /* Populate the SecurityPolicies */
- UA_ByteString localCertificate = UA_BYTESTRING_NULL;
- if(certificate)
- localCertificate = *certificate;
+
+ UA_ByteString_init(&context->localSymSigningKey);
+ UA_ByteString_init(&context->localSymEncryptingKey);
+ UA_ByteString_init(&context->localSymIv);
+ UA_ByteString_init(&context->remoteSymSigningKey);
+ UA_ByteString_init(&context->remoteSymEncryptingKey);
+ UA_ByteString_init(&context->remoteSymIv);
+
UA_StatusCode retval =
- UA_SecurityPolicy_None(&config->securityPolicies[config->securityPoliciesSize],
- localCertificate, &config->logger);
+ UA_copyCertificate(&context->remoteCertificate, remoteCertificate);
if(retval != UA_STATUSCODE_GOOD) {
- if(config->securityPoliciesSize == 0) {
- UA_free(config->securityPolicies);
- config->securityPolicies = NULL;
- }
+ UA_free(context);
return retval;
}
- config->securityPoliciesSize++;
- return UA_STATUSCODE_GOOD;
-}
-
-UA_EXPORT UA_StatusCode
-UA_ServerConfig_addEndpoint(UA_ServerConfig *config, const UA_String securityPolicyUri,
- UA_MessageSecurityMode securityMode) {
- /* Allocate the endpoint */
- UA_EndpointDescription *tmp = (UA_EndpointDescription *)
- UA_realloc(config->endpoints,
- sizeof(UA_EndpointDescription) * (1 + config->endpointsSize));
- if(!tmp) {
- return UA_STATUSCODE_BADOUTOFMEMORY;
+ /* decode to X509 */
+ context->remoteCertificateX509 = UA_OpenSSL_LoadCertificate(&context->remoteCertificate);
+ if(context->remoteCertificateX509 == NULL) {
+ UA_ByteString_clear(&context->remoteCertificate);
+ UA_free(context);
}
- config->endpoints = tmp;
- /* Lookup the security policy */
- const UA_SecurityPolicy *policy = NULL;
- for (size_t i = 0; i < config->securityPoliciesSize; ++i) {
- if (UA_String_equal(&securityPolicyUri, &config->securityPolicies[i].policyUri)) {
- policy = &config->securityPolicies[i];
- break;
- }
- }
- if (!policy)
- return UA_STATUSCODE_BADINVALIDARGUMENT;
+ context->policyContext =
+ (Policy_Context_Basic256Sha256 *)securityPolicy->policyContext;
+ *channelContext = context;
- /* Populate the endpoint */
- UA_StatusCode retval =
- createEndpoint(config, &config->endpoints[config->endpointsSize],
- policy, securityMode);
- if(retval != UA_STATUSCODE_GOOD)
- return retval;
- config->endpointsSize++;
+ UA_LOG_INFO(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY,
+ "The basic256sha256 security policy channel with openssl is created.");
return UA_STATUSCODE_GOOD;
}
-UA_EXPORT UA_StatusCode
-UA_ServerConfig_addAllEndpoints(UA_ServerConfig *config) {
- /* Allocate the endpoints */
- UA_EndpointDescription * tmp = (UA_EndpointDescription *)
- UA_realloc(config->endpoints,
- sizeof(UA_EndpointDescription) *
- (2 * config->securityPoliciesSize + config->endpointsSize));
- if(!tmp) {
- return UA_STATUSCODE_BADOUTOFMEMORY;
- }
- config->endpoints = tmp;
+/* delete the channel context */
- /* Populate the endpoints */
- for(size_t i = 0; i < config->securityPoliciesSize; ++i) {
- if(UA_String_equal(&UA_SECURITY_POLICY_NONE_URI, &config->securityPolicies[i].policyUri)) {
- UA_StatusCode retval =
- createEndpoint(config, &config->endpoints[config->endpointsSize],
- &config->securityPolicies[i], UA_MESSAGESECURITYMODE_NONE);
- if(retval != UA_STATUSCODE_GOOD)
- return retval;
- config->endpointsSize++;
- } else {
- UA_StatusCode retval =
- createEndpoint(config, &config->endpoints[config->endpointsSize],
- &config->securityPolicies[i], UA_MESSAGESECURITYMODE_SIGN);
- if(retval != UA_STATUSCODE_GOOD)
- return retval;
- config->endpointsSize++;
+static void
+UA_ChannelModule_Delete_Context(void * channelContext) {
+ if(!channelContext)
+ return;
+
+ Channel_Context_Basic256Sha256 * cc = (Channel_Context_Basic256Sha256 *)channelContext;
+ X509_free(cc->remoteCertificateX509);
+ UA_ByteString_clear(&cc->remoteCertificate);
+ UA_ByteString_clear(&cc->localSymSigningKey);
+ UA_ByteString_clear(&cc->localSymEncryptingKey);
+ UA_ByteString_clear(&cc->localSymIv);
+ UA_ByteString_clear(&cc->remoteSymSigningKey);
+ UA_ByteString_clear(&cc->remoteSymEncryptingKey);
+ UA_ByteString_clear(&cc->remoteSymIv);
+
+ UA_LOG_INFO(cc->policyContext->logger, UA_LOGCATEGORY_SECURITYPOLICY,
+ "The basic256sha256 security policy channel with openssl is deleted.");
+ UA_free(cc);
+}
- retval = createEndpoint(config, &config->endpoints[config->endpointsSize],
- &config->securityPolicies[i],
- UA_MESSAGESECURITYMODE_SIGNANDENCRYPT);
- if(retval != UA_STATUSCODE_GOOD)
- return retval;
- config->endpointsSize++;
- }
- }
+/* Verifies the signature of the message using the provided keys in the context.
+ * AsymmetricSignatureAlgorithm_RSA-PKCS15-SHA2-256 */
+static UA_StatusCode
+UA_AsySig_Basic256Sha256_Verify(void *channelContext,
+ const UA_ByteString *message,
+ const UA_ByteString *signature) {
+ if(message == NULL || signature == NULL || channelContext == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+ Channel_Context_Basic256Sha256 * cc =
+ (Channel_Context_Basic256Sha256 *) channelContext;
+ return UA_OpenSSL_RSA_PKCS1_V15_SHA256_Verify(message, cc->remoteCertificateX509,
+ signature);
+}
+
+/* Compares the supplied certificate with the certificate
+ * in the endpoint context
+ */
+
+static UA_StatusCode
+UA_compareCertificateThumbprint(const UA_SecurityPolicy * securityPolicy,
+ const UA_ByteString * certificateThumbprint) {
+ if(securityPolicy == NULL || certificateThumbprint == NULL)
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+ Policy_Context_Basic256Sha256 *pc = (Policy_Context_Basic256Sha256 *)
+ securityPolicy->policyContext;
+ if(!UA_ByteString_equal(certificateThumbprint, &pc->localCertThumbprint))
+ return UA_STATUSCODE_BADCERTIFICATEINVALID;
return UA_STATUSCODE_GOOD;
}
-UA_EXPORT UA_StatusCode
-UA_ServerConfig_setMinimalCustomBuffer(UA_ServerConfig *config, UA_UInt16 portNumber,
- const UA_ByteString *certificate,
- UA_UInt32 sendBufferSize,
- UA_UInt32 recvBufferSize) {
- if(!config)
+/* Generates a thumbprint for the specified certificate */
+
+static UA_StatusCode
+UA_makeCertificateThumbprint(const UA_SecurityPolicy * securityPolicy,
+ const UA_ByteString * certificate,
+ UA_ByteString * thumbprint) {
+ return UA_Openssl_X509_GetCertificateThumbprint(certificate, thumbprint, false);
+}
+
+static UA_StatusCode
+UA_Asym_Basic256Sha256_Decrypt(void * channelContext, UA_ByteString * data) {
+ if(channelContext == NULL || data == NULL)
return UA_STATUSCODE_BADINVALIDARGUMENT;
- UA_StatusCode retval = setDefaultConfig(config);
- if(retval != UA_STATUSCODE_GOOD) {
- UA_ServerConfig_clean(config);
- return retval;
- }
+ Channel_Context_Basic256Sha256 * cc =
+ (Channel_Context_Basic256Sha256 *) channelContext;
+ return UA_Openssl_RSA_Oaep_Decrypt(data, cc->policyContext->localPrivateKey);
+}
- retval = addDefaultNetworkLayers(config, portNumber, sendBufferSize, recvBufferSize);
- if(retval != UA_STATUSCODE_GOOD) {
- UA_ServerConfig_clean(config);
- return retval;
- }
+static size_t
+UA_Asym_Basic256Sha256_getRemoteSignatureSize(const void *channelContext) {
+ if(channelContext == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
- /* Allocate the SecurityPolicies */
- retval = UA_ServerConfig_addSecurityPolicyNone(config, certificate);
- if(retval != UA_STATUSCODE_GOOD) {
- UA_ServerConfig_clean(config);
- return retval;
- }
+ const Channel_Context_Basic256Sha256 * cc =
+ (const Channel_Context_Basic256Sha256 *) channelContext;
+ UA_Int32 keyLen = 0;
+ UA_Openssl_RSA_Public_GetKeyLength(cc->remoteCertificateX509, &keyLen);
+ return (size_t) keyLen;
+}
- /* Initialize the Access Control plugin */
- retval = UA_AccessControl_default(config, true,
- &config->securityPolicies[config->securityPoliciesSize-1].policyUri,
- usernamePasswordsSize, usernamePasswords);
- if(retval != UA_STATUSCODE_GOOD) {
- UA_ServerConfig_clean(config);
- return retval;
- }
+static size_t
+UA_AsySig_Basic256Sha256_getLocalSignatureSize(const void *channelContext) {
+ if(channelContext == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
- /* Allocate the endpoint */
- retval = UA_ServerConfig_addEndpoint(config, UA_SECURITY_POLICY_NONE_URI,
- UA_MESSAGESECURITYMODE_NONE);
- if(retval != UA_STATUSCODE_GOOD) {
- UA_ServerConfig_clean(config);
- return retval;
- }
+ const Channel_Context_Basic256Sha256 *cc =
+ (const Channel_Context_Basic256Sha256 *) channelContext;
+ Policy_Context_Basic256Sha256 * pc = cc->policyContext;
+ UA_Int32 keyLen = 0;
+ UA_Openssl_RSA_Private_GetKeyLength(pc->localPrivateKey, &keyLen);
+ return (size_t) keyLen;
+}
- UA_LOG_WARNING(&config->logger, UA_LOGCATEGORY_USERLAND,
- "AcceptAll Certificate Verification. "
- "Any remote certificate will be accepted.");
+static size_t
+UA_AsymEn_Basic256Sha256_getRemotePlainTextBlockSize(const void *channelContext) {
+ if(channelContext == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
- return UA_STATUSCODE_GOOD;
+ const Channel_Context_Basic256Sha256 *cc =
+ (const Channel_Context_Basic256Sha256 *) channelContext;
+ UA_Int32 keyLen = 0;
+ UA_Openssl_RSA_Public_GetKeyLength(cc->remoteCertificateX509, &keyLen);
+ return (size_t) keyLen - UA_SECURITYPOLICY_BASIC256SHA256_RSAPADDING_LEN;
}
-#ifdef UA_ENABLE_ENCRYPTION
+static size_t
+UA_AsymEn_Basic256Sha256_getRemoteBlockSize(const void *channelContext) {
+ if(channelContext == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
-UA_EXPORT UA_StatusCode
-UA_ServerConfig_addSecurityPolicyBasic128Rsa15(UA_ServerConfig *config,
- const UA_ByteString *certificate,
- const UA_ByteString *privateKey) {
- /* Allocate the SecurityPolicies */
- UA_SecurityPolicy *tmp = (UA_SecurityPolicy *)
- UA_realloc(config->securityPolicies,
- sizeof(UA_SecurityPolicy) * (1 + config->securityPoliciesSize));
- if(!tmp)
- return UA_STATUSCODE_BADOUTOFMEMORY;
- config->securityPolicies = tmp;
-
- /* Populate the SecurityPolicies */
- UA_ByteString localCertificate = UA_BYTESTRING_NULL;
- UA_ByteString localPrivateKey = UA_BYTESTRING_NULL;
- if(certificate)
- localCertificate = *certificate;
- if(privateKey)
- localPrivateKey = *privateKey;
- UA_StatusCode retval =
- UA_SecurityPolicy_Basic128Rsa15(&config->securityPolicies[config->securityPoliciesSize],
- localCertificate, localPrivateKey, &config->logger);
- if(retval != UA_STATUSCODE_GOOD) {
- if(config->securityPoliciesSize == 0) {
- UA_free(config->securityPolicies);
- config->securityPolicies = NULL;
- }
- return retval;
- }
+ const Channel_Context_Basic256Sha256 * cc =
+ (const Channel_Context_Basic256Sha256 *) channelContext;
+ UA_Int32 keyLen = 0;
+ UA_Openssl_RSA_Public_GetKeyLength(cc->remoteCertificateX509, &keyLen);
+ return (size_t) keyLen;
+}
- config->securityPoliciesSize++;
- return UA_STATUSCODE_GOOD;
+static size_t
+UA_AsymEn_Basic256Sha256_getRemoteKeyLength(const void *channelContext) {
+ if(channelContext == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ const Channel_Context_Basic256Sha256 *cc =
+ (const Channel_Context_Basic256Sha256 *) channelContext;
+ UA_Int32 keyLen = 0;
+ UA_Openssl_RSA_Public_GetKeyLength(cc->remoteCertificateX509, &keyLen);
+ return (size_t) keyLen * 8;
}
-UA_EXPORT UA_StatusCode
-UA_ServerConfig_addSecurityPolicyBasic256(UA_ServerConfig *config,
- const UA_ByteString *certificate,
- const UA_ByteString *privateKey) {
- /* Allocate the SecurityPolicies */
- UA_SecurityPolicy *tmp = (UA_SecurityPolicy *)
- UA_realloc(config->securityPolicies,
- sizeof(UA_SecurityPolicy) * (1 + config->securityPoliciesSize));
- if(!tmp)
- return UA_STATUSCODE_BADOUTOFMEMORY;
- config->securityPolicies = tmp;
+static UA_StatusCode
+UA_Sym_Basic256Sha256_generateNonce(void *policyContext,
+ UA_ByteString *out) {
+ UA_Int32 rc = RAND_bytes(out->data, (int) out->length);
+ if(rc != 1)
+ return UA_STATUSCODE_BADUNEXPECTEDERROR;
+ return UA_STATUSCODE_GOOD;
+}
+
+static size_t
+UA_SymEn_Basic256Sha256_getLocalKeyLength(const void *channelContext) {
+ /* 32 bytes 256 bits */
+ return UA_SECURITYPOLICY_BASIC256SHA256_SYM_ENCRYPTION_KEY_LENGTH;
+}
+
+static size_t
+UA_SymSig_Basic256Sha256_getLocalKeyLength(const void *channelContext) {
+ /* 32 bytes 256 bits */
+ return UA_SECURITYPOLICY_BASIC256SHA256_SYM_SIGNING_KEY_LENGTH;
+}
+
+static UA_StatusCode
+UA_Sym_Basic256Sha256_generateKey(void *policyContext,
+ const UA_ByteString *secret,
+ const UA_ByteString *seed,
+ UA_ByteString *out) {
+ return UA_Openssl_Random_Key_PSHA256_Derive(secret, seed, out);
+}
+
+static UA_StatusCode
+UA_ChannelModule_Basic256Sha256_setLocalSymSigningKey(void * channelContext,
+ const UA_ByteString * key) {
+ if(key == NULL || channelContext == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+ Channel_Context_Basic256Sha256 * cc = (Channel_Context_Basic256Sha256 *) channelContext;
+ UA_ByteString_clear(&cc->localSymSigningKey);
+ return UA_ByteString_copy(key, &cc->localSymSigningKey);
+}
+
+static UA_StatusCode
+UA_ChannelM_Basic256Sha256_setLocalSymEncryptingKey(void * channelContext,
+ const UA_ByteString * key) {
+ if(key == NULL || channelContext == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+ Channel_Context_Basic256Sha256 * cc = (Channel_Context_Basic256Sha256 *) channelContext;
+ UA_ByteString_clear(&cc->localSymEncryptingKey);
+ return UA_ByteString_copy(key, &cc->localSymEncryptingKey);
+}
+
+static UA_StatusCode
+UA_ChannelM_Basic256Sha256_setLocalSymIv(void * channelContext,
+ const UA_ByteString * iv) {
+ if(iv == NULL || channelContext == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+ Channel_Context_Basic256Sha256 * cc = (Channel_Context_Basic256Sha256 *) channelContext;
+ UA_ByteString_clear(&cc->localSymIv);
+ return UA_ByteString_copy(iv, &cc->localSymIv);
+}
+
+static size_t
+UA_SymEn_Basic256Sha256_getRemoteKeyLength(const void * channelContext) {
+ /* 32 bytes 256 bits */
+ return UA_SECURITYPOLICY_BASIC256SHA256_SYM_ENCRYPTION_KEY_LENGTH;
+}
+
+static size_t
+UA_SymEn_Basic256Sha256_getBlockSize(const void *channelContext) {
+ return UA_SECURITYPOLICY_BASIC256SHA256_SYM_ENCRYPTION_BLOCK_SIZE;
+}
+
+static size_t
+UA_SymSig_Basic256Sha256_getRemoteKeyLength(const void * channelContext) {
+ /* 32 bytes 256 bits */
+ return UA_SECURITYPOLICY_BASIC256SHA256_SYM_SIGNING_KEY_LENGTH;
+}
+
+static UA_StatusCode
+UA_ChannelM_Basic256Sha256_setRemoteSymSigningKey(void *channelContext,
+ const UA_ByteString * key) {
+ if(key == NULL || channelContext == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+ Channel_Context_Basic256Sha256 * cc = (Channel_Context_Basic256Sha256 *) channelContext;
+ UA_ByteString_clear(&cc->remoteSymSigningKey);
+ return UA_ByteString_copy(key, &cc->remoteSymSigningKey);
+}
+
+static UA_StatusCode
+UA_ChannelM_Basic256Sha256_setRemoteSymEncryptingKey(void *channelContext,
+ const UA_ByteString * key) {
+ if(key == NULL || channelContext == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+ Channel_Context_Basic256Sha256 * cc = (Channel_Context_Basic256Sha256 *) channelContext;
+ UA_ByteString_clear(&cc->remoteSymEncryptingKey);
+ return UA_ByteString_copy(key, &cc->remoteSymEncryptingKey);
+}
+
+static UA_StatusCode
+UA_ChannelM_Basic256Sha256_setRemoteSymIv(void *channelContext,
+ const UA_ByteString * key) {
+ if(key == NULL || channelContext == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+ Channel_Context_Basic256Sha256 * cc = (Channel_Context_Basic256Sha256 *) channelContext;
+ UA_ByteString_clear(&cc->remoteSymIv);
+ return UA_ByteString_copy(key, &cc->remoteSymIv);
+}
+
+static UA_StatusCode
+UA_AsySig_Basic256Sha256_sign(void *channelContext, const UA_ByteString * message,
+ UA_ByteString *signature) {
+ if(channelContext == NULL || message == NULL || signature == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+ Channel_Context_Basic256Sha256 *cc = (Channel_Context_Basic256Sha256 *) channelContext;
+ Policy_Context_Basic256Sha256 *pc = cc->policyContext;
+ return UA_Openssl_RSA_PKCS1_V15_SHA256_Sign(message, pc->localPrivateKey, signature);
+}
+
+static UA_StatusCode
+UA_AsymEn_Basic256Sha256_encrypt(void *channelContext, UA_ByteString *data) {
+ if(channelContext == NULL || data == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+ Channel_Context_Basic256Sha256 * cc =
+ (Channel_Context_Basic256Sha256 *) channelContext;
+ return UA_Openssl_RSA_OAEP_Encrypt(data, UA_SECURITYPOLICY_BASIC256SHA256_RSAPADDING_LEN,
+ cc->remoteCertificateX509);
+}
+
+static size_t
+UA_SymSig_Basic256Sha256_getRemoteSignatureSize(const void *channelContext) {
+ return UA_SHA256_LENGTH;
+}
+
+static UA_StatusCode
+UA_SymSig_Basic256Sha256_verify(void *channelContext, const UA_ByteString *message,
+ const UA_ByteString *signature) {
+ if(channelContext == NULL || message == NULL || signature == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
- /* Populate the SecurityPolicies */
- UA_ByteString localCertificate = UA_BYTESTRING_NULL;
- UA_ByteString localPrivateKey = UA_BYTESTRING_NULL;
- if(certificate)
- localCertificate = *certificate;
- if(privateKey)
- localPrivateKey = *privateKey;
- UA_StatusCode retval =
- UA_SecurityPolicy_Basic256(&config->securityPolicies[config->securityPoliciesSize],
- localCertificate, localPrivateKey, &config->logger);
- if(retval != UA_STATUSCODE_GOOD) {
- if(config->securityPoliciesSize == 0) {
- UA_free(config->securityPolicies);
- config->securityPolicies = NULL;
- }
- return retval;
- }
+ Channel_Context_Basic256Sha256 * cc = (Channel_Context_Basic256Sha256 *) channelContext;
+ return UA_OpenSSL_HMAC_SHA256_Verify(message, &cc->remoteSymSigningKey, signature);
+}
- config->securityPoliciesSize++;
- return UA_STATUSCODE_GOOD;
+static UA_StatusCode
+UA_SymSig_Basic256Sha256_sign(void *channelContext, const UA_ByteString *message,
+ UA_ByteString *signature) {
+ if(channelContext == NULL || message == NULL || signature == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ Channel_Context_Basic256Sha256 * cc = (Channel_Context_Basic256Sha256 *) channelContext;
+ return UA_OpenSSL_HMAC_SHA256_Sign(message, &cc->localSymSigningKey, signature);
}
-UA_EXPORT UA_StatusCode
-UA_ServerConfig_addSecurityPolicyBasic256Sha256(UA_ServerConfig *config,
- const UA_ByteString *certificate,
- const UA_ByteString *privateKey) {
- /* Allocate the SecurityPolicies */
- UA_SecurityPolicy *tmp = (UA_SecurityPolicy *)
- UA_realloc(config->securityPolicies,
- sizeof(UA_SecurityPolicy) * (1 + config->securityPoliciesSize));
- if(!tmp)
- return UA_STATUSCODE_BADOUTOFMEMORY;
- config->securityPolicies = tmp;
+static size_t
+UA_SymSig_Basic256Sha256_getLocalSignatureSize(const void * channelContext) {
+ return UA_SHA256_LENGTH;
+}
+
+static UA_StatusCode
+UA_SymEn_Basic256Sha256_decrypt(void *channelContext, UA_ByteString *data) {
+ if(channelContext == NULL || data == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+ Channel_Context_Basic256Sha256 * cc = (Channel_Context_Basic256Sha256 *) channelContext;
+ return UA_OpenSSL_AES_256_CBC_Decrypt(&cc->remoteSymIv,
+ &cc->remoteSymEncryptingKey, data);
+}
+
+static UA_StatusCode
+UA_SymEn_Basic256Sha256_encrypt(void *channelContext, UA_ByteString *data) {
+ if(channelContext == NULL || data == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
- /* Populate the SecurityPolicies */
- UA_ByteString localCertificate = UA_BYTESTRING_NULL;
- UA_ByteString localPrivateKey = UA_BYTESTRING_NULL;
- if(certificate)
- localCertificate = *certificate;
- if(privateKey)
- localPrivateKey = *privateKey;
+ Channel_Context_Basic256Sha256 * cc = (Channel_Context_Basic256Sha256 *) channelContext;
+ return UA_OpenSSL_AES_256_CBC_Encrypt(&cc->localSymIv, &cc->localSymEncryptingKey, data);
+}
+
+static UA_StatusCode
+UA_ChannelM_Basic256Sha256_compareCertificate(const void *channelContext,
+ const UA_ByteString *certificate) {
+ if(channelContext == NULL || certificate == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ const Channel_Context_Basic256Sha256 * cc =
+ (const Channel_Context_Basic256Sha256 *) channelContext;
+ return UA_OpenSSL_X509_compare(certificate, cc->remoteCertificateX509);
+}
+
+static size_t
+UA_AsymEn_Basic256Sha256_getLocalKeyLength(const void *channelContext) {
+ if(channelContext == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ const Channel_Context_Basic256Sha256 * cc =
+ (const Channel_Context_Basic256Sha256 *) channelContext;
+ Policy_Context_Basic256Sha256 *pc = cc->policyContext;
+ UA_Int32 keyLen = 0;
+ UA_Openssl_RSA_Private_GetKeyLength(pc->localPrivateKey, &keyLen);
+ return (size_t) keyLen * 8;
+}
+
+/* the main entry of Basic256Sha256 */
+
+UA_StatusCode
+UA_SecurityPolicy_Basic256Sha256(UA_SecurityPolicy *policy,
+ const UA_ByteString localCertificate,
+ const UA_ByteString localPrivateKey,
+ const UA_Logger *logger) {
+ UA_SecurityPolicyAsymmetricModule *asymmetricModule = &policy->asymmetricModule;
+ UA_SecurityPolicySymmetricModule *symmetricModule = &policy->symmetricModule;
+ UA_SecurityPolicyChannelModule *channelModule = &policy->channelModule;
+ UA_LOG_INFO(logger, UA_LOGCATEGORY_SECURITYPOLICY,
+ "The basic256sha256 security policy with openssl is added.");
+
+ UA_Openssl_Init();
+ memset(policy, 0, sizeof(UA_SecurityPolicy));
+ policy->logger = logger;
+ policy->policyUri =
+ UA_STRING("http://opcfoundation.org/UA/SecurityPolicy#Basic256Sha256\0");
+
+ /* Set ChannelModule context */
+ channelModule->newContext = UA_ChannelModule_New_Context;
+ channelModule->deleteContext = UA_ChannelModule_Delete_Context;
+ channelModule->setLocalSymSigningKey =
+ UA_ChannelModule_Basic256Sha256_setLocalSymSigningKey;
+ channelModule->setLocalSymEncryptingKey =
+ UA_ChannelM_Basic256Sha256_setLocalSymEncryptingKey;
+ channelModule->setLocalSymIv = UA_ChannelM_Basic256Sha256_setLocalSymIv;
+ channelModule->setRemoteSymSigningKey =
+ UA_ChannelM_Basic256Sha256_setRemoteSymSigningKey;
+ channelModule->setRemoteSymEncryptingKey =
+ UA_ChannelM_Basic256Sha256_setRemoteSymEncryptingKey;
+ channelModule->setRemoteSymIv = UA_ChannelM_Basic256Sha256_setRemoteSymIv;
+ channelModule->compareCertificate = UA_ChannelM_Basic256Sha256_compareCertificate;
UA_StatusCode retval =
- UA_SecurityPolicy_Basic256Sha256(&config->securityPolicies[config->securityPoliciesSize],
- localCertificate, localPrivateKey, &config->logger);
- if(retval != UA_STATUSCODE_GOOD) {
- if(config->securityPoliciesSize == 0) {
- UA_free(config->securityPolicies);
- config->securityPolicies = NULL;
- }
+ UA_OpenSSL_LoadLocalCertificate(&localCertificate, &policy->localCertificate);
+ if(retval != UA_STATUSCODE_GOOD)
return retval;
- }
- config->securityPoliciesSize++;
- return UA_STATUSCODE_GOOD;
-}
+ /* AsymmetricModule - signature algorithm */
+ UA_SecurityPolicySignatureAlgorithm *asySigAlgorithm =
+ &asymmetricModule->cryptoModule.signatureAlgorithm;
+ asySigAlgorithm->uri = UA_STRING("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256\0");
+ asySigAlgorithm->verify = UA_AsySig_Basic256Sha256_Verify;
+ asySigAlgorithm->sign = UA_AsySig_Basic256Sha256_sign;
+ asySigAlgorithm->getLocalSignatureSize = UA_AsySig_Basic256Sha256_getLocalSignatureSize;
+ asySigAlgorithm->getRemoteSignatureSize = UA_Asym_Basic256Sha256_getRemoteSignatureSize;
+ asySigAlgorithm->getLocalKeyLength = NULL;
+ asySigAlgorithm->getRemoteKeyLength = NULL;
-/* Always returns UA_STATUSCODE_GOOD. Logs a warning if policies could not be added. */
-UA_EXPORT UA_StatusCode
-UA_ServerConfig_addAllSecurityPolicies(UA_ServerConfig *config,
- const UA_ByteString *certificate,
- const UA_ByteString *privateKey) {
- /* Populate the SecurityPolicies */
- UA_ByteString localCertificate = UA_BYTESTRING_NULL;
- UA_ByteString localPrivateKey = UA_BYTESTRING_NULL;
- if(certificate)
- localCertificate = *certificate;
- if(privateKey)
- localPrivateKey = *privateKey;
+ /* AsymmetricModule encryption algorithm */
+ UA_SecurityPolicyEncryptionAlgorithm *asymEncryAlg =
+ &asymmetricModule->cryptoModule.encryptionAlgorithm;
+ asymEncryAlg->uri = UA_STRING("http://www.w3.org/2001/04/xmlenc#rsa-oaep\0");
+ asymEncryAlg->encrypt = UA_AsymEn_Basic256Sha256_encrypt;
+ asymEncryAlg->decrypt = UA_Asym_Basic256Sha256_Decrypt;
+ asymEncryAlg->getLocalKeyLength = UA_AsymEn_Basic256Sha256_getLocalKeyLength;
+ asymEncryAlg->getRemoteKeyLength = UA_AsymEn_Basic256Sha256_getRemoteKeyLength;
+ asymEncryAlg->getRemoteBlockSize = UA_AsymEn_Basic256Sha256_getRemoteBlockSize;
+ asymEncryAlg->getRemotePlainTextBlockSize =
+ UA_AsymEn_Basic256Sha256_getRemotePlainTextBlockSize;
- UA_StatusCode retval = UA_ServerConfig_addSecurityPolicyNone(config, &localCertificate);
- if(retval != UA_STATUSCODE_GOOD) {
- UA_LOG_WARNING(&config->logger, UA_LOGCATEGORY_USERLAND,
- "Could not add SecurityPolicy#None with error code %s",
- UA_StatusCode_name(retval));
- }
+ /* AsymmetricModule */
+ asymmetricModule->compareCertificateThumbprint = UA_compareCertificateThumbprint;
+ asymmetricModule->makeCertificateThumbprint = UA_makeCertificateThumbprint;
- retval = UA_ServerConfig_addSecurityPolicyBasic128Rsa15(config, &localCertificate, &localPrivateKey);
- if(retval != UA_STATUSCODE_GOOD) {
- UA_LOG_WARNING(&config->logger, UA_LOGCATEGORY_USERLAND,
- "Could not add SecurityPolicy#Basic128Rsa15 with error code %s",
- UA_StatusCode_name(retval));
- }
+ /* SymmetricModule */
+ symmetricModule->secureChannelNonceLength = 32;
+ symmetricModule->generateNonce = UA_Sym_Basic256Sha256_generateNonce;
+ symmetricModule->generateKey = UA_Sym_Basic256Sha256_generateKey;
- retval = UA_ServerConfig_addSecurityPolicyBasic256(config, &localCertificate, &localPrivateKey);
- if(retval != UA_STATUSCODE_GOOD) {
- UA_LOG_WARNING(&config->logger, UA_LOGCATEGORY_USERLAND,
- "Could not add SecurityPolicy#Basic256 with error code %s",
- UA_StatusCode_name(retval));
- }
+ /* Symmetric encryption Algorithm */
+ UA_SecurityPolicyEncryptionAlgorithm *symEncryptionAlgorithm =
+ &symmetricModule->cryptoModule.encryptionAlgorithm;
+ symEncryptionAlgorithm->uri =
+ UA_STRING("http://www.w3.org/2001/04/xmlenc#aes256-cbc\0");
+ symEncryptionAlgorithm->encrypt = UA_SymEn_Basic256Sha256_encrypt;
+ symEncryptionAlgorithm->decrypt = UA_SymEn_Basic256Sha256_decrypt;
+ symEncryptionAlgorithm->getLocalKeyLength = UA_SymEn_Basic256Sha256_getLocalKeyLength;
+ symEncryptionAlgorithm->getRemoteKeyLength = UA_SymEn_Basic256Sha256_getRemoteKeyLength;
+ symEncryptionAlgorithm->getRemoteBlockSize = UA_SymEn_Basic256Sha256_getBlockSize;
+ symEncryptionAlgorithm->getRemotePlainTextBlockSize = UA_SymEn_Basic256Sha256_getBlockSize;
- retval = UA_ServerConfig_addSecurityPolicyBasic256Sha256(config, &localCertificate, &localPrivateKey);
+ /* Symmetric signature Algorithm */
+ UA_SecurityPolicySignatureAlgorithm *symSignatureAlgorithm =
+ &symmetricModule->cryptoModule.signatureAlgorithm;
+ symSignatureAlgorithm->uri =
+ UA_STRING("http://www.w3.org/2000/09/xmldsig#hmac-sha2-256\0");
+ symSignatureAlgorithm->verify = UA_SymSig_Basic256Sha256_verify;
+ symSignatureAlgorithm->sign = UA_SymSig_Basic256Sha256_sign;
+ symSignatureAlgorithm->getLocalSignatureSize =
+ UA_SymSig_Basic256Sha256_getLocalSignatureSize;
+ symSignatureAlgorithm->getRemoteSignatureSize =
+ UA_SymSig_Basic256Sha256_getRemoteSignatureSize;
+ symSignatureAlgorithm->getLocalKeyLength =
+ UA_SymSig_Basic256Sha256_getLocalKeyLength;
+ symSignatureAlgorithm->getRemoteKeyLength =
+ UA_SymSig_Basic256Sha256_getRemoteKeyLength;
+
+ policy->clear = UA_Policy_Clear_Context;
+ retval = UA_Policy_New_Context(policy, localPrivateKey, logger);
if(retval != UA_STATUSCODE_GOOD) {
- UA_LOG_WARNING(&config->logger, UA_LOGCATEGORY_USERLAND,
- "Could not add SecurityPolicy#Basic256Sha256 with error code %s",
- UA_StatusCode_name(retval));
+ UA_ByteString_clear(&policy->localCertificate);
+ return retval;
}
+ /* Use the same signature algorithm as the asymmetric component for
+ * certificate signing (see standard) */
+ policy->certificateSigningAlgorithm =
+ policy->asymmetricModule.cryptoModule.signatureAlgorithm;
+
return UA_STATUSCODE_GOOD;
}
-UA_EXPORT UA_StatusCode
-UA_ServerConfig_setDefaultWithSecurityPolicies(UA_ServerConfig *conf,
- UA_UInt16 portNumber,
- const UA_ByteString *certificate,
- const UA_ByteString *privateKey,
- const UA_ByteString *trustList,
- size_t trustListSize,
- const UA_ByteString *issuerList,
- size_t issuerListSize,
- const UA_ByteString *revocationList,
- size_t revocationListSize) {
- UA_StatusCode retval = setDefaultConfig(conf);
- if(retval != UA_STATUSCODE_GOOD) {
- UA_ServerConfig_clean(conf);
- return retval;
- }
+#endif
- retval = UA_CertificateVerification_Trustlist(&conf->certificateVerification,
- trustList, trustListSize,
- issuerList, issuerListSize,
- revocationList, revocationListSize);
- if (retval != UA_STATUSCODE_GOOD)
- return retval;
+/**** amalgamated original file "/plugins/crypto/openssl/ua_openssl_aes128sha256rsaoaep.c" ****/
- retval = addDefaultNetworkLayers(conf, portNumber, 0, 0);
- if(retval != UA_STATUSCODE_GOOD) {
- UA_ServerConfig_clean(conf);
- return retval;
- }
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Copyright 2020 (c) Wind River Systems, Inc.
+ */
- retval = UA_ServerConfig_addAllSecurityPolicies(conf, certificate, privateKey);
- if(retval != UA_STATUSCODE_GOOD) {
- UA_ServerConfig_clean(conf);
- return retval;
+
+#if defined(UA_ENABLE_ENCRYPTION_OPENSSL) || defined(UA_ENABLE_ENCRYPTION_LIBRESSL)
+
+
+#include <openssl/hmac.h>
+#include <openssl/sha.h>
+#include <openssl/rsa.h>
+#include <openssl/x509.h>
+#include <openssl/rand.h>
+#include <openssl/rsa.h>
+
+#define UA_SHA256_LENGTH 32 /* 256 bit */
+#define UA_SECURITYPOLICY_AES128SHA256RSAOAEP_RSAPADDING_LEN 42
+#define UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_SIGNING_KEY_LENGTH 32
+#define UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_ENCRYPTION_KEY_LENGTH 16
+#define UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_ENCRYPTION_BLOCK_SIZE 16
+#define UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_PLAIN_TEXT_BLOCK_SIZE 16
+#define UA_SECURITYPOLICY_AES128SHA256RSAOAEP_MINASYMKEYLENGTH 256
+#define UA_SECURITYPOLICY_AES128SHA256RSAOAEP_MAXASYMKEYLENGTH 512
+
+typedef struct {
+ EVP_PKEY *localPrivateKey;
+ UA_ByteString localCertThumbprint;
+ const UA_Logger *logger;
+} Policy_Context_Aes128Sha256RsaOaep;
+
+typedef struct {
+ UA_ByteString localSymSigningKey;
+ UA_ByteString localSymEncryptingKey;
+ UA_ByteString localSymIv;
+ UA_ByteString remoteSymSigningKey;
+ UA_ByteString remoteSymEncryptingKey;
+ UA_ByteString remoteSymIv;
+
+ Policy_Context_Aes128Sha256RsaOaep *policyContext;
+ UA_ByteString remoteCertificate;
+ X509 *remoteCertificateX509; /* X509 */
+} Channel_Context_Aes128Sha256RsaOaep;
+
+/* create the policy context */
+
+static UA_StatusCode
+UA_Policy_Aes128Sha256RsaOaep_New_Context(UA_SecurityPolicy *securityPolicy,
+ const UA_ByteString localPrivateKey,
+ const UA_Logger *logger) {
+ Policy_Context_Aes128Sha256RsaOaep *context =
+ (Policy_Context_Aes128Sha256RsaOaep *)UA_malloc(
+ sizeof(Policy_Context_Aes128Sha256RsaOaep));
+ if(context == NULL) {
+ return UA_STATUSCODE_BADOUTOFMEMORY;
}
- retval = UA_AccessControl_default(conf, true,
- &conf->securityPolicies[conf->securityPoliciesSize-1].policyUri,
- usernamePasswordsSize, usernamePasswords);
- if(retval != UA_STATUSCODE_GOOD) {
- UA_ServerConfig_clean(conf);
- return retval;
+ context->localPrivateKey = UA_OpenSSL_LoadPrivateKey(&localPrivateKey);
+ if (!context->localPrivateKey) {
+ UA_free(context);
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
}
- retval = UA_ServerConfig_addAllEndpoints(conf);
+ UA_StatusCode retval = UA_Openssl_X509_GetCertificateThumbprint(
+ &securityPolicy->localCertificate, &context->localCertThumbprint, true);
if(retval != UA_STATUSCODE_GOOD) {
- UA_ServerConfig_clean(conf);
+ EVP_PKEY_free(context->localPrivateKey);
+ UA_free(context);
return retval;
}
+ context->logger = logger;
+ securityPolicy->policyContext = context;
+
return UA_STATUSCODE_GOOD;
}
-#endif
+/* clear the policy context */
-/***************************/
-/* Default Client Settings */
-/***************************/
+static void
+UA_Policy_Aes128Sha256RsaOaep_Clear_Context(UA_SecurityPolicy *policy) {
+ if(policy == NULL)
+ return;
-UA_Client * UA_Client_new() {
- UA_ClientConfig config;
- memset(&config, 0, sizeof(UA_ClientConfig));
- config.logger.log = UA_Log_Stdout_log;
- config.logger.context = NULL;
- config.logger.clear = UA_Log_Stdout_clear;
- return UA_Client_newWithConfig(&config);
-}
+ UA_ByteString_clear(&policy->localCertificate);
-UA_StatusCode
-UA_ClientConfig_setDefault(UA_ClientConfig *config) {
- config->timeout = 5000;
- config->secureChannelLifeTime = 10 * 60 * 1000; /* 10 minutes */
+ /* delete all allocated members in the context */
- if(!config->logger.log) {
- config->logger.log = UA_Log_Stdout_log;
- config->logger.context = NULL;
- config->logger.clear = UA_Log_Stdout_clear;
+ Policy_Context_Aes128Sha256RsaOaep *pc =
+ (Policy_Context_Aes128Sha256RsaOaep *)policy->policyContext;
+ if (pc == NULL) {
+ return;
}
- config->localConnectionConfig = UA_ConnectionConfig_default;
+ EVP_PKEY_free(pc->localPrivateKey);
+ UA_ByteString_clear(&pc->localCertThumbprint);
+ UA_free(pc);
- /* Certificate Verification that accepts every certificate. Can be
- * overwritten when the policy is specialized. */
- UA_CertificateVerification_AcceptAll(&config->certificateVerification);
- UA_LOG_WARNING(&config->logger, UA_LOGCATEGORY_USERLAND,
- "AcceptAll Certificate Verification. "
- "Any remote certificate will be accepted.");
+ return;
+}
- /* With encryption enabled, the applicationUri needs to match the URI from
- * the certificate */
- config->clientDescription.applicationUri = UA_STRING_ALLOC(APPLICATION_URI);
- config->clientDescription.applicationType = UA_APPLICATIONTYPE_CLIENT;
+/* create the channel context */
- if(config->securityPoliciesSize > 0) {
- UA_LOG_ERROR(&config->logger, UA_LOGCATEGORY_NETWORK,
- "Could not initialize a config that already has SecurityPolicies");
+static UA_StatusCode
+UA_ChannelModule_Aes128Sha256RsaOaep_New_Context(const UA_SecurityPolicy *securityPolicy,
+ const UA_ByteString *remoteCertificate,
+ void **channelContext) {
+ if(securityPolicy == NULL || remoteCertificate == NULL || channelContext == NULL) {
return UA_STATUSCODE_BADINTERNALERROR;
}
-
- config->securityPolicies = (UA_SecurityPolicy*)UA_malloc(sizeof(UA_SecurityPolicy));
- if(!config->securityPolicies)
+ Channel_Context_Aes128Sha256RsaOaep *context =
+ (Channel_Context_Aes128Sha256RsaOaep *)UA_malloc(
+ sizeof(Channel_Context_Aes128Sha256RsaOaep));
+ if(context == NULL) {
return UA_STATUSCODE_BADOUTOFMEMORY;
- UA_StatusCode retval = UA_SecurityPolicy_None(config->securityPolicies,
- UA_BYTESTRING_NULL, &config->logger);
+ }
+
+ UA_ByteString_init(&context->localSymSigningKey);
+ UA_ByteString_init(&context->localSymEncryptingKey);
+ UA_ByteString_init(&context->localSymIv);
+ UA_ByteString_init(&context->remoteSymSigningKey);
+ UA_ByteString_init(&context->remoteSymEncryptingKey);
+ UA_ByteString_init(&context->remoteSymIv);
+
+ UA_StatusCode retval =
+ UA_copyCertificate(&context->remoteCertificate, remoteCertificate);
if(retval != UA_STATUSCODE_GOOD) {
- UA_free(config->securityPolicies);
- config->securityPolicies = NULL;
+ UA_free(context);
return retval;
}
- config->securityPoliciesSize = 1;
- config->initConnectionFunc = UA_ClientConnectionTCP_init; /* for async client */
- config->pollConnectionFunc = UA_ClientConnectionTCP_poll; /* for async connection */
-
- config->customDataTypes = NULL;
- config->stateCallback = NULL;
- config->connectivityCheckInterval = 0;
+ /* decode to X509 */
+ context->remoteCertificateX509 = UA_OpenSSL_LoadCertificate(&context->remoteCertificate);
+ if (context->remoteCertificateX509 == NULL) {
+ UA_ByteString_clear (&context->remoteCertificate);
+ UA_free (context);
+ return UA_STATUSCODE_BADCERTIFICATECHAININCOMPLETE;
+ }
- config->requestedSessionTimeout = 1200000; /* requestedSessionTimeout */
+ context->policyContext =
+ (Policy_Context_Aes128Sha256RsaOaep *)(securityPolicy->policyContext);
- config->inactivityCallback = NULL;
- config->clientContext = NULL;
+ *channelContext = context;
-#ifdef UA_ENABLE_SUBSCRIPTIONS
- config->outStandingPublishRequests = 10;
- config->subscriptionInactivityCallback = NULL;
-#endif
+ UA_LOG_INFO(
+ securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY,
+ "The Aes128Sha256RsaOaep security policy channel with openssl is created.");
return UA_STATUSCODE_GOOD;
}
-#ifdef UA_ENABLE_ENCRYPTION
-UA_StatusCode
-UA_ClientConfig_setDefaultEncryption(UA_ClientConfig *config,
- UA_ByteString localCertificate, UA_ByteString privateKey,
- const UA_ByteString *trustList, size_t trustListSize,
- const UA_ByteString *revocationList, size_t revocationListSize) {
- UA_StatusCode retval = UA_ClientConfig_setDefault(config);
- if(retval != UA_STATUSCODE_GOOD)
- return retval;
-
- retval = UA_CertificateVerification_Trustlist(&config->certificateVerification,
- trustList, trustListSize,
- NULL, 0,
- revocationList, revocationListSize);
- if(retval != UA_STATUSCODE_GOOD)
- return retval;
+/* delete the channel context */
- /* Populate SecurityPolicies */
- UA_SecurityPolicy *sp = (UA_SecurityPolicy*)
- UA_realloc(config->securityPolicies, sizeof(UA_SecurityPolicy) * 4);
- if(!sp)
- return UA_STATUSCODE_BADOUTOFMEMORY;
- config->securityPolicies = sp;
-
- retval = UA_SecurityPolicy_Basic128Rsa15(&config->securityPolicies[config->securityPoliciesSize],
- localCertificate, privateKey, &config->logger);
- if(retval == UA_STATUSCODE_GOOD) {
- ++config->securityPoliciesSize;
- } else {
- UA_LOG_WARNING(&config->logger, UA_LOGCATEGORY_USERLAND,
- "Could not add SecurityPolicy#Basic128Rsa15 with error code %s",
- UA_StatusCode_name(retval));
+static void
+UA_ChannelModule_Aes128Sha256RsaOaep_Delete_Context(void *channelContext) {
+ if(channelContext != NULL) {
+ Channel_Context_Aes128Sha256RsaOaep *cc =
+ (Channel_Context_Aes128Sha256RsaOaep *)channelContext;
+ X509_free(cc->remoteCertificateX509);
+ UA_ByteString_clear(&cc->remoteCertificate);
+ UA_ByteString_clear(&cc->localSymSigningKey);
+ UA_ByteString_clear(&cc->localSymEncryptingKey);
+ UA_ByteString_clear(&cc->localSymIv);
+ UA_ByteString_clear(&cc->remoteSymSigningKey);
+ UA_ByteString_clear(&cc->remoteSymEncryptingKey);
+ UA_ByteString_clear(&cc->remoteSymIv);
+
+ UA_LOG_INFO(
+ cc->policyContext->logger, UA_LOGCATEGORY_SECURITYPOLICY,
+ "The Aes128Sha256RsaOaep security policy channel with openssl is deleted.");
+ UA_free(cc);
}
+}
- retval = UA_SecurityPolicy_Basic256(&config->securityPolicies[config->securityPoliciesSize],
- localCertificate, privateKey, &config->logger);
- if(retval == UA_STATUSCODE_GOOD) {
- ++config->securityPoliciesSize;
- } else {
- UA_LOG_WARNING(&config->logger, UA_LOGCATEGORY_USERLAND,
- "Could not add SecurityPolicy#Basic256 with error code %s",
- UA_StatusCode_name(retval));
- }
+/* Verifies the signature of the message using the provided keys in the context.
+ * AsymmetricSignatureAlgorithm_RSA-PKCS15-SHA2-256
+ */
- retval = UA_SecurityPolicy_Basic256Sha256(&config->securityPolicies[config->securityPoliciesSize],
- localCertificate, privateKey, &config->logger);
- if(retval == UA_STATUSCODE_GOOD) {
- ++config->securityPoliciesSize;
- } else {
- UA_LOG_WARNING(&config->logger, UA_LOGCATEGORY_USERLAND,
- "Could not add SecurityPolicy#Basic256Sha256 with error code %s",
- UA_StatusCode_name(retval));
+static UA_StatusCode
+UA_AsySig_Aes128Sha256RsaOaep_Verify(void *channelContext, const UA_ByteString *message,
+ const UA_ByteString *signature) {
+ if(message == NULL || signature == NULL || channelContext == NULL) {
+ return UA_STATUSCODE_BADINTERNALERROR;
}
- if(config->securityPoliciesSize == 0) {
- UA_free(config->securityPolicies);
- config->securityPolicies = NULL;
- }
+ Channel_Context_Aes128Sha256RsaOaep *cc =
+ (Channel_Context_Aes128Sha256RsaOaep *)channelContext;
+ UA_StatusCode retval = UA_OpenSSL_RSA_PKCS1_V15_SHA256_Verify(
+ message, cc->remoteCertificateX509, signature);
- return UA_STATUSCODE_GOOD;
+ return retval;
}
-#endif
-
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/plugins/securityPolicies/ua_securitypolicy_none.c" ***********************************/
-/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
- * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
- *
- * Copyright 2017-2018 (c) Mark Giraud, Fraunhofer IOSB
- * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
+/* Compares the supplied certificate with the certificate
+ * in the endpoint context
*/
-
static UA_StatusCode
-verify_none(const UA_SecurityPolicy *securityPolicy,
- void *channelContext,
- const UA_ByteString *message,
- const UA_ByteString *signature) {
+UA_compareCertificateThumbprint_Aes128Sha256RsaOaep(const UA_SecurityPolicy *securityPolicy,
+ const UA_ByteString *certificateThumbprint) {
+ if(securityPolicy == NULL || certificateThumbprint == NULL) {
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+ }
+ Policy_Context_Aes128Sha256RsaOaep *pc =
+ (Policy_Context_Aes128Sha256RsaOaep *)securityPolicy->policyContext;
+ if(!UA_ByteString_equal(certificateThumbprint, &pc->localCertThumbprint))
+ return UA_STATUSCODE_BADCERTIFICATEINVALID;
return UA_STATUSCODE_GOOD;
}
+/* Generates a thumbprint for the specified certificate */
+
static UA_StatusCode
-sign_none(const UA_SecurityPolicy *securityPolicy,
- void *channelContext,
- const UA_ByteString *message,
- UA_ByteString *signature) {
- return UA_STATUSCODE_GOOD;
+UA_makeCertificateThumbprint_Aes128Sha256RsaOaep(const UA_SecurityPolicy *securityPolicy,
+ const UA_ByteString *certificate,
+ UA_ByteString *thumbprint) {
+ return UA_Openssl_X509_GetCertificateThumbprint(certificate, thumbprint, false);
+}
+
+static UA_StatusCode
+UA_Asym_Aes128Sha256RsaOaep_Decrypt(void *channelContext, UA_ByteString *data) {
+ if(channelContext == NULL || data == NULL)
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+
+ Channel_Context_Aes128Sha256RsaOaep *cc = (Channel_Context_Aes128Sha256RsaOaep *)channelContext;
+ UA_StatusCode ret = UA_Openssl_RSA_Oaep_Decrypt(data, cc->policyContext->localPrivateKey);
+ return ret;
}
static size_t
-length_none(const UA_SecurityPolicy *securityPolicy,
- const void *channelContext) {
- return 0;
+UA_Asym_Aes128Sha256RsaOaep_getRemoteSignatureSize(const void *channelContext) {
+ if(channelContext == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ const Channel_Context_Aes128Sha256RsaOaep *cc = (const Channel_Context_Aes128Sha256RsaOaep *)channelContext;
+ UA_Int32 keyLen = 0;
+ UA_Openssl_RSA_Public_GetKeyLength(cc->remoteCertificateX509, &keyLen);
+ return (size_t)keyLen;
+}
+
+static size_t
+UA_AsySig_Aes128Sha256RsaOaep_getLocalSignatureSize(const void *channelContext) {
+ if(channelContext == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ const Channel_Context_Aes128Sha256RsaOaep *cc = (const Channel_Context_Aes128Sha256RsaOaep *)channelContext;
+ Policy_Context_Aes128Sha256RsaOaep *pc = cc->policyContext;
+ UA_Int32 keyLen = 0;
+ UA_Openssl_RSA_Private_GetKeyLength(pc->localPrivateKey, &keyLen);
+ return (size_t)keyLen;
+}
+
+static size_t
+UA_AsymEn_Aes128Sha256RsaOaep_getRemotePlainTextBlockSize(const void *channelContext) {
+ if(channelContext == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ const Channel_Context_Aes128Sha256RsaOaep *cc =
+ (const Channel_Context_Aes128Sha256RsaOaep *)channelContext;
+ UA_Int32 keyLen = 0;
+ UA_Openssl_RSA_Public_GetKeyLength(cc->remoteCertificateX509, &keyLen);
+ return (size_t)keyLen - UA_SECURITYPOLICY_AES128SHA256RSAOAEP_RSAPADDING_LEN;
+}
+
+static size_t
+UA_AsymEn_Aes128Sha256RsaOaep_getRemoteBlockSize(const void *channelContext) {
+ if(channelContext == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ const Channel_Context_Aes128Sha256RsaOaep *cc =
+ (const Channel_Context_Aes128Sha256RsaOaep *)channelContext;
+ UA_Int32 keyLen = 0;
+ UA_Openssl_RSA_Public_GetKeyLength(cc->remoteCertificateX509, &keyLen);
+ return (size_t)keyLen;
+}
+
+static size_t
+UA_AsymEn_Aes128Sha256RsaOaep_getRemoteKeyLength(const void *channelContext) {
+ if(channelContext == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ const Channel_Context_Aes128Sha256RsaOaep *cc =
+ (const Channel_Context_Aes128Sha256RsaOaep *)channelContext;
+ UA_Int32 keyLen = 0;
+ UA_Openssl_RSA_Public_GetKeyLength(cc->remoteCertificateX509, &keyLen);
+ return (size_t)keyLen * 8;
}
static UA_StatusCode
-encrypt_none(const UA_SecurityPolicy *securityPolicy,
- void *channelContext,
- UA_ByteString *data) {
+UA_Sym_Aes128Sha256RsaOaep_generateNonce(void *policyContext,
+ UA_ByteString *out) {
+ UA_Int32 rc = RAND_bytes(out->data, (int)out->length);
+ if(rc != 1) {
+ return UA_STATUSCODE_BADUNEXPECTEDERROR;
+ }
return UA_STATUSCODE_GOOD;
}
+static size_t
+UA_SymEn_Aes128Sha256RsaOaep_getLocalKeyLength(const void *channelContext) {
+ /* 32 bytes 256 bits */
+ return UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_ENCRYPTION_KEY_LENGTH;
+}
+
+static size_t
+UA_SymSig_Aes128Sha256RsaOaep_getLocalKeyLength(const void *channelContext) {
+ /* 32 bytes 256 bits */
+ return UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_SIGNING_KEY_LENGTH;
+}
+
static UA_StatusCode
-decrypt_none(const UA_SecurityPolicy *securityPolicy,
- void *channelContext,
- UA_ByteString *data) {
- return UA_STATUSCODE_GOOD;
+UA_Sym_Aes128Sha256RsaOaep_generateKey(void *policyContext,
+ const UA_ByteString *secret,
+ const UA_ByteString *seed, UA_ByteString *out) {
+ return UA_Openssl_Random_Key_PSHA256_Derive(secret, seed, out);
}
static UA_StatusCode
-makeThumbprint_none(const UA_SecurityPolicy *securityPolicy,
- const UA_ByteString *certificate,
- UA_ByteString *thumbprint) {
- return UA_STATUSCODE_GOOD;
+UA_ChannelModule_Aes128Sha256RsaOaep_setLocalSymSigningKey(void *channelContext,
+ const UA_ByteString *key) {
+ if(key == NULL || channelContext == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+ Channel_Context_Aes128Sha256RsaOaep *cc =
+ (Channel_Context_Aes128Sha256RsaOaep *)channelContext;
+ UA_ByteString_clear(&cc->localSymSigningKey);
+ return UA_ByteString_copy(key, &cc->localSymSigningKey);
}
static UA_StatusCode
-compareThumbprint_none(const UA_SecurityPolicy *securityPolicy,
- const UA_ByteString *certificateThumbprint) {
- return UA_STATUSCODE_GOOD;
+UA_ChannelM_Aes128Sha256RsaOaep_setLocalSymEncryptingKey(void *channelContext,
+ const UA_ByteString *key) {
+ if(key == NULL || channelContext == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+ Channel_Context_Aes128Sha256RsaOaep *cc =
+ (Channel_Context_Aes128Sha256RsaOaep *)channelContext;
+ UA_ByteString_clear(&cc->localSymEncryptingKey);
+ return UA_ByteString_copy(key, &cc->localSymEncryptingKey);
}
static UA_StatusCode
-generateKey_none(const UA_SecurityPolicy *securityPolicy,
- const UA_ByteString *secret,
- const UA_ByteString *seed,
- UA_ByteString *out) {
- return UA_STATUSCODE_GOOD;
+UA_ChannelM_Aes128Sha256RsaOaep_setLocalSymIv(void *channelContext,
+ const UA_ByteString *iv) {
+ if(iv == NULL || channelContext == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+ Channel_Context_Aes128Sha256RsaOaep *cc =
+ (Channel_Context_Aes128Sha256RsaOaep *)channelContext;
+ UA_ByteString_clear(&cc->localSymIv);
+ return UA_ByteString_copy(iv, &cc->localSymIv);
+}
+
+static size_t
+UA_SymEn_Aes128Sha256RsaOaep_getRemoteKeyLength(const void *channelContext) {
+ /* 32 bytes 256 bits */
+ return UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_ENCRYPTION_KEY_LENGTH;
+}
+
+static size_t
+UA_SymEn_Aes128Sha256RsaOaep_getBlockSize(const void *channelContext) {
+ return UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_ENCRYPTION_BLOCK_SIZE;
+}
+
+static size_t
+UA_SymSig_Aes128Sha256RsaOaep_getRemoteKeyLength(const void *channelContext) {
+ /* 32 bytes 256 bits */
+ return UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_SIGNING_KEY_LENGTH;
}
-/* Use the non-cryptographic RNG to set the nonce */
static UA_StatusCode
-generateNonce_none(const UA_SecurityPolicy *securityPolicy, UA_ByteString *out) {
- if(securityPolicy == NULL || out == NULL)
+UA_ChannelM_Aes128Sha256RsaOaep_setRemoteSymSigningKey(void *channelContext,
+ const UA_ByteString *key) {
+ if(key == NULL || channelContext == NULL)
return UA_STATUSCODE_BADINTERNALERROR;
+ Channel_Context_Aes128Sha256RsaOaep *cc =
+ (Channel_Context_Aes128Sha256RsaOaep *)channelContext;
+ UA_ByteString_clear(&cc->remoteSymSigningKey);
+ return UA_ByteString_copy(key, &cc->remoteSymSigningKey);
+}
- if(out->length == 0)
- return UA_STATUSCODE_GOOD;
+static UA_StatusCode
+UA_ChannelM_Aes128Sha256RsaOaep_setRemoteSymEncryptingKey(void *channelContext,
+ const UA_ByteString *key) {
+ if(key == NULL || channelContext == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+ Channel_Context_Aes128Sha256RsaOaep *cc =
+ (Channel_Context_Aes128Sha256RsaOaep *)channelContext;
+ UA_ByteString_clear(&cc->remoteSymEncryptingKey);
+ return UA_ByteString_copy(key, &cc->remoteSymEncryptingKey);
+}
- /* Fill blocks of four byte */
- size_t i = 0;
- while(i + 3 < out->length) {
- UA_UInt32 randNumber = UA_UInt32_random();
- memcpy(&out->data[i], &randNumber, 4);
- i = i+4;
- }
+static UA_StatusCode
+UA_ChannelM_Aes128Sha256RsaOaep_setRemoteSymIv(void *channelContext,
+ const UA_ByteString *key) {
+ if(key == NULL || channelContext == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+ Channel_Context_Aes128Sha256RsaOaep *cc = (Channel_Context_Aes128Sha256RsaOaep *)channelContext;
+ UA_ByteString_clear(&cc->remoteSymIv);
+ return UA_ByteString_copy(key, &cc->remoteSymIv);
+}
- /* Fill the remaining byte */
- UA_UInt32 randNumber = UA_UInt32_random();
- memcpy(&out->data[i], &randNumber, out->length % 4);
+static UA_StatusCode
+UA_AsySig_Aes128Sha256RsaOaep_sign(void *channelContext, const UA_ByteString *message,
+ UA_ByteString *signature) {
+ if(channelContext == NULL || message == NULL ||
+ signature == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+ Channel_Context_Aes128Sha256RsaOaep *cc = (Channel_Context_Aes128Sha256RsaOaep *)channelContext;
+ Policy_Context_Aes128Sha256RsaOaep *pc = cc->policyContext;
+ return UA_Openssl_RSA_PKCS1_V15_SHA256_Sign(message, pc->localPrivateKey, signature);
+}
- return UA_STATUSCODE_GOOD;
+static UA_StatusCode
+UA_AsymEn_Aes128Sha256RsaOaep_encrypt(void *channelContext, UA_ByteString *data) {
+ if(channelContext == NULL || data == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+ Channel_Context_Aes128Sha256RsaOaep *cc =
+ (Channel_Context_Aes128Sha256RsaOaep *)channelContext;
+ return UA_Openssl_RSA_OAEP_Encrypt(
+ data, UA_SECURITYPOLICY_AES128SHA256RSAOAEP_RSAPADDING_LEN,
+ cc->remoteCertificateX509);
+}
+
+static size_t
+UA_SymSig_Aes128Sha256RsaOaep_getRemoteSignatureSize(const void *channelContext) {
+ return UA_SHA256_LENGTH;
}
static UA_StatusCode
-newContext_none(const UA_SecurityPolicy *securityPolicy,
- const UA_ByteString *remoteCertificate,
- void **channelContext) {
- return UA_STATUSCODE_GOOD;
+UA_SymSig_Aes128Sha256RsaOaep_verify(void *channelContext, const UA_ByteString *message,
+ const UA_ByteString *signature) {
+ if(channelContext == NULL || message == NULL ||
+ signature == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ Channel_Context_Aes128Sha256RsaOaep *cc =
+ (Channel_Context_Aes128Sha256RsaOaep *)channelContext;
+ return UA_OpenSSL_HMAC_SHA256_Verify(message, &cc->remoteSymSigningKey, signature);
}
-static void
-deleteContext_none(void *channelContext) {
+static UA_StatusCode
+UA_SymSig_Aes128Sha256RsaOaep_sign(void *channelContext, const UA_ByteString *message,
+ UA_ByteString *signature) {
+ if(channelContext == NULL || message == NULL ||
+ signature == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ Channel_Context_Aes128Sha256RsaOaep *cc =
+ (Channel_Context_Aes128Sha256RsaOaep *)channelContext;
+ return UA_OpenSSL_HMAC_SHA256_Sign(message, &cc->localSymSigningKey, signature);
+}
+
+static size_t
+UA_SymSig_Aes128Sha256RsaOaep_getLocalSignatureSize(const void *channelContext) {
+ return UA_SHA256_LENGTH;
}
static UA_StatusCode
-setContextValue_none(void *channelContext,
- const UA_ByteString *key) {
- return UA_STATUSCODE_GOOD;
+UA_SymEn_Aes128Sha256RsaOaep_decrypt(void *channelContext, UA_ByteString *data) {
+ if(channelContext == NULL || data == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+ Channel_Context_Aes128Sha256RsaOaep *cc =
+ (Channel_Context_Aes128Sha256RsaOaep *)channelContext;
+ return UA_OpenSSL_AES_128_CBC_Decrypt(&cc->remoteSymIv, &cc->remoteSymEncryptingKey,
+ data);
}
static UA_StatusCode
-compareCertificate_none(const void *channelContext,
- const UA_ByteString *certificate) {
- return UA_STATUSCODE_GOOD;
+UA_SymEn_Aes128Sha256RsaOaep_encrypt(void *channelContext, UA_ByteString *data) {
+ if(channelContext == NULL || data == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ Channel_Context_Aes128Sha256RsaOaep *cc =
+ (Channel_Context_Aes128Sha256RsaOaep *)channelContext;
+ return UA_OpenSSL_AES_128_CBC_Encrypt(&cc->localSymIv, &cc->localSymEncryptingKey,
+ data);
}
static UA_StatusCode
-updateCertificateAndPrivateKey_none(UA_SecurityPolicy *policy,
- const UA_ByteString newCertificate,
- const UA_ByteString newPrivateKey) {
- UA_ByteString_deleteMembers(&policy->localCertificate);
- UA_ByteString_copy(&newCertificate, &policy->localCertificate);
- return UA_STATUSCODE_GOOD;
+UA_ChannelM_Aes128Sha256RsaOaep_compareCertificate(const void *channelContext,
+ const UA_ByteString *certificate) {
+ if(channelContext == NULL || certificate == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ const Channel_Context_Aes128Sha256RsaOaep *cc = (const Channel_Context_Aes128Sha256RsaOaep *)channelContext;
+ return UA_OpenSSL_X509_compare(certificate, cc->remoteCertificateX509);
}
+static size_t
+UA_AsymEn_Aes128Sha256RsaOaep_getLocalKeyLength(const void *channelContext) {
+ if(channelContext == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
-static void
-policy_clear_none(UA_SecurityPolicy *policy) {
- UA_ByteString_deleteMembers(&policy->localCertificate);
+ const Channel_Context_Aes128Sha256RsaOaep *cc = (const Channel_Context_Aes128Sha256RsaOaep *)channelContext;
+ Policy_Context_Aes128Sha256RsaOaep *pc = cc->policyContext;
+ UA_Int32 keyLen = 0;
+ UA_Openssl_RSA_Private_GetKeyLength(pc->localPrivateKey, &keyLen);
+ return (size_t)keyLen * 8;
}
+/* the main entry of Aes128Sha256RsaOaep */
+
UA_StatusCode
-UA_SecurityPolicy_None(UA_SecurityPolicy *policy, const UA_ByteString localCertificate,
- const UA_Logger *logger) {
- policy->policyContext = (void *)(uintptr_t)logger;
- policy->policyUri = UA_STRING("http://opcfoundation.org/UA/SecurityPolicy#None");
+UA_SecurityPolicy_Aes128Sha256RsaOaep(UA_SecurityPolicy *policy,
+ const UA_ByteString localCertificate,
+ const UA_ByteString localPrivateKey,
+ const UA_Logger *logger) {
+
+ UA_SecurityPolicyAsymmetricModule *const asymmetricModule = &policy->asymmetricModule;
+ UA_SecurityPolicySymmetricModule *const symmetricModule = &policy->symmetricModule;
+ UA_SecurityPolicyChannelModule *const channelModule = &policy->channelModule;
+ UA_StatusCode retval;
+
+ UA_LOG_INFO(logger, UA_LOGCATEGORY_SECURITYPOLICY,
+ "The Aes128Sha256RsaOaep security policy with openssl is added.");
+
+ UA_Openssl_Init();
+ memset(policy, 0, sizeof(UA_SecurityPolicy));
policy->logger = logger;
- UA_ByteString_copy(&localCertificate, &policy->localCertificate);
+ policy->policyUri =
+ UA_STRING("http://opcfoundation.org/UA/SecurityPolicy#Aes128_Sha256_RsaOaep\0");
- policy->symmetricModule.generateKey = generateKey_none;
- policy->symmetricModule.generateNonce = generateNonce_none;
+ /* set ChannelModule context */
- UA_SecurityPolicySignatureAlgorithm *sym_signatureAlgorithm =
- &policy->symmetricModule.cryptoModule.signatureAlgorithm;
- sym_signatureAlgorithm->uri = UA_STRING_NULL;
- sym_signatureAlgorithm->verify = verify_none;
- sym_signatureAlgorithm->sign = sign_none;
- sym_signatureAlgorithm->getLocalSignatureSize = length_none;
- sym_signatureAlgorithm->getRemoteSignatureSize = length_none;
- sym_signatureAlgorithm->getLocalKeyLength = length_none;
- sym_signatureAlgorithm->getRemoteKeyLength = length_none;
+ channelModule->newContext = UA_ChannelModule_Aes128Sha256RsaOaep_New_Context;
+ channelModule->deleteContext = UA_ChannelModule_Aes128Sha256RsaOaep_Delete_Context;
+ channelModule->setLocalSymSigningKey =
+ UA_ChannelModule_Aes128Sha256RsaOaep_setLocalSymSigningKey;
+ channelModule->setLocalSymEncryptingKey =
+ UA_ChannelM_Aes128Sha256RsaOaep_setLocalSymEncryptingKey;
+ channelModule->setLocalSymIv = UA_ChannelM_Aes128Sha256RsaOaep_setLocalSymIv;
+ channelModule->setRemoteSymSigningKey =
+ UA_ChannelM_Aes128Sha256RsaOaep_setRemoteSymSigningKey;
+ channelModule->setRemoteSymEncryptingKey =
+ UA_ChannelM_Aes128Sha256RsaOaep_setRemoteSymEncryptingKey;
+ channelModule->setRemoteSymIv = UA_ChannelM_Aes128Sha256RsaOaep_setRemoteSymIv;
+ channelModule->compareCertificate =
+ UA_ChannelM_Aes128Sha256RsaOaep_compareCertificate;
+
+ /* Copy the certificate and add a NULL to the end */
+
+ retval = UA_copyCertificate(&policy->localCertificate, &localCertificate);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
- UA_SecurityPolicyEncryptionAlgorithm *sym_encryptionAlgorithm =
- &policy->symmetricModule.cryptoModule.encryptionAlgorithm;
- sym_encryptionAlgorithm->uri = UA_STRING_NULL;
- sym_encryptionAlgorithm->encrypt = encrypt_none;
- sym_encryptionAlgorithm->decrypt = decrypt_none;
- sym_encryptionAlgorithm->getLocalKeyLength = length_none;
- sym_encryptionAlgorithm->getRemoteKeyLength = length_none;
- sym_encryptionAlgorithm->getLocalBlockSize = length_none;
- sym_encryptionAlgorithm->getRemoteBlockSize = length_none;
- sym_encryptionAlgorithm->getLocalPlainTextBlockSize = length_none;
- sym_encryptionAlgorithm->getRemotePlainTextBlockSize = length_none;
- policy->symmetricModule.secureChannelNonceLength = 0;
+ /* AsymmetricModule - signature algorithm */
- policy->asymmetricModule.makeCertificateThumbprint = makeThumbprint_none;
- policy->asymmetricModule.compareCertificateThumbprint = compareThumbprint_none;
+ UA_SecurityPolicySignatureAlgorithm *asySigAlgorithm =
+ &asymmetricModule->cryptoModule.signatureAlgorithm;
+ asySigAlgorithm->uri =
+ UA_STRING("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256\0");
+ asySigAlgorithm->verify = UA_AsySig_Aes128Sha256RsaOaep_Verify;
+ asySigAlgorithm->getRemoteSignatureSize =
+ UA_Asym_Aes128Sha256RsaOaep_getRemoteSignatureSize;
+ asySigAlgorithm->getLocalSignatureSize =
+ UA_AsySig_Aes128Sha256RsaOaep_getLocalSignatureSize;
+ asySigAlgorithm->sign = UA_AsySig_Aes128Sha256RsaOaep_sign;
+ asySigAlgorithm->getLocalKeyLength = NULL;
+ asySigAlgorithm->getRemoteKeyLength = NULL;
- // This only works for none since symmetric and asymmetric crypto modules do the same i.e. nothing
- policy->asymmetricModule.cryptoModule = policy->symmetricModule.cryptoModule;
+ /* AsymmetricModule encryption algorithm */
- // Use the same signing algorithm as for asymmetric signing
- policy->certificateSigningAlgorithm = policy->asymmetricModule.cryptoModule.signatureAlgorithm;
+ UA_SecurityPolicyEncryptionAlgorithm *asymEncryAlg =
+ &asymmetricModule->cryptoModule.encryptionAlgorithm;
+ asymEncryAlg->uri = UA_STRING("http://www.w3.org/2001/04/xmlenc#rsa-oaep\0");
+ asymEncryAlg->decrypt = UA_Asym_Aes128Sha256RsaOaep_Decrypt;
+ asymEncryAlg->getRemotePlainTextBlockSize =
+ UA_AsymEn_Aes128Sha256RsaOaep_getRemotePlainTextBlockSize;
+ asymEncryAlg->getRemoteBlockSize = UA_AsymEn_Aes128Sha256RsaOaep_getRemoteBlockSize;
+ asymEncryAlg->getRemoteKeyLength = UA_AsymEn_Aes128Sha256RsaOaep_getRemoteKeyLength;
+ asymEncryAlg->encrypt = UA_AsymEn_Aes128Sha256RsaOaep_encrypt;
+ asymEncryAlg->getLocalKeyLength = UA_AsymEn_Aes128Sha256RsaOaep_getLocalKeyLength;
- policy->channelModule.newContext = newContext_none;
- policy->channelModule.deleteContext = deleteContext_none;
- policy->channelModule.setLocalSymEncryptingKey = setContextValue_none;
- policy->channelModule.setLocalSymSigningKey = setContextValue_none;
- policy->channelModule.setLocalSymIv = setContextValue_none;
- policy->channelModule.setRemoteSymEncryptingKey = setContextValue_none;
- policy->channelModule.setRemoteSymSigningKey = setContextValue_none;
- policy->channelModule.setRemoteSymIv = setContextValue_none;
- policy->channelModule.compareCertificate = compareCertificate_none;
- policy->updateCertificateAndPrivateKey = updateCertificateAndPrivateKey_none;
- policy->clear = policy_clear_none;
+ /* asymmetricModule */
+
+ asymmetricModule->compareCertificateThumbprint =
+ UA_compareCertificateThumbprint_Aes128Sha256RsaOaep;
+ asymmetricModule->makeCertificateThumbprint =
+ UA_makeCertificateThumbprint_Aes128Sha256RsaOaep;
+
+ /* SymmetricModule */
+
+ symmetricModule->secureChannelNonceLength = 32;
+ symmetricModule->generateNonce = UA_Sym_Aes128Sha256RsaOaep_generateNonce;
+ symmetricModule->generateKey = UA_Sym_Aes128Sha256RsaOaep_generateKey;
+
+ /* Symmetric encryption Algorithm */
+
+ UA_SecurityPolicyEncryptionAlgorithm *symEncryptionAlgorithm =
+ &symmetricModule->cryptoModule.encryptionAlgorithm;
+ symEncryptionAlgorithm->uri =
+ UA_STRING("http://www.w3.org/2001/04/xmlenc#aes128-cbc\0");
+ symEncryptionAlgorithm->getLocalKeyLength = UA_SymEn_Aes128Sha256RsaOaep_getLocalKeyLength;
+ symEncryptionAlgorithm->getRemoteKeyLength = UA_SymEn_Aes128Sha256RsaOaep_getRemoteKeyLength;
+ symEncryptionAlgorithm->getRemoteBlockSize = UA_SymEn_Aes128Sha256RsaOaep_getBlockSize;
+ symEncryptionAlgorithm->getRemotePlainTextBlockSize = UA_SymEn_Aes128Sha256RsaOaep_getBlockSize;
+ symEncryptionAlgorithm->decrypt = UA_SymEn_Aes128Sha256RsaOaep_decrypt;
+ symEncryptionAlgorithm->encrypt = UA_SymEn_Aes128Sha256RsaOaep_encrypt;
+
+ /* Symmetric signature Algorithm */
+
+ UA_SecurityPolicySignatureAlgorithm *symSignatureAlgorithm =
+ &symmetricModule->cryptoModule.signatureAlgorithm;
+ symSignatureAlgorithm->uri = UA_STRING("http://www.w3.org/2000/09/xmldsig#hmac-sha2-256\0");
+ symSignatureAlgorithm->getLocalKeyLength = UA_SymSig_Aes128Sha256RsaOaep_getLocalKeyLength;
+ symSignatureAlgorithm->getRemoteKeyLength = UA_SymSig_Aes128Sha256RsaOaep_getRemoteKeyLength;
+ symSignatureAlgorithm->getRemoteSignatureSize = UA_SymSig_Aes128Sha256RsaOaep_getRemoteSignatureSize;
+ symSignatureAlgorithm->verify = UA_SymSig_Aes128Sha256RsaOaep_verify;
+ symSignatureAlgorithm->sign = UA_SymSig_Aes128Sha256RsaOaep_sign;
+ symSignatureAlgorithm->getLocalSignatureSize = UA_SymSig_Aes128Sha256RsaOaep_getLocalSignatureSize;
+
+ retval = UA_Policy_Aes128Sha256RsaOaep_New_Context(policy, localPrivateKey, logger);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_ByteString_clear(&policy->localCertificate);
+ return retval;
+ }
+ policy->clear = UA_Policy_Aes128Sha256RsaOaep_Clear_Context;
+
+ /* Use the same signature algorithm as the asymmetric component for
+ certificate signing (see standard) */
+
+ policy->certificateSigningAlgorithm =
+ policy->asymmetricModule.cryptoModule.signatureAlgorithm;
return UA_STATUSCODE_GOOD;
}
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/plugins/ua_log_syslog.c" ***********************************/
+#endif
+
+/**** amalgamated original file "/plugins/crypto/openssl/ua_openssl_create_certificate.c" ****/
-/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
- * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Copyright 2021 (c) Christian von Arnim, ISW University of Stuttgart (for VDW and umati)
+ * Copyright 2022 (c) Wind River Systems, Inc.
*
- * Copyright 2020 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
*/
-#if defined(__linux__) || defined(__unix__)
-#include <syslog.h>
+#if defined(UA_ENABLE_ENCRYPTION_OPENSSL) || defined(UA_ENABLE_ENCRYPTION_LIBRESSL)
-const char *syslogLevelNames[6] = {"trace", "debug", "info",
- "warn", "error", "fatal"};
-const char *syslogCategoryNames[7] = {"network", "channel", "session", "server",
- "client", "userland", "securitypolicy"};
-#ifdef __clang__
-__attribute__((__format__(__printf__, 4 , 0)))
-#endif
-static void
-UA_Log_Syslog_log(void *context, UA_LogLevel level, UA_LogCategory category,
- const char *msg, va_list args) {
- /* Assume that context is casted to UA_LogLevel */
- if(context != NULL && (UA_LogLevel)(uintptr_t)context > level)
- return;
+#include <openssl/pem.h>
+#include <openssl/x509v3.h>
- int priority = LOG_INFO;
- switch(level) {
- case UA_LOGLEVEL_DEBUG:
- priority = LOG_DEBUG;
- break;
- case UA_LOGLEVEL_INFO:
- priority = LOG_INFO;
- break;
- case UA_LOGLEVEL_WARNING:
- priority = LOG_WARNING;
- break;
- case UA_LOGLEVEL_ERROR:
- priority = LOG_ERR;
- break;
- case UA_LOGLEVEL_FATAL:
- priority = LOG_CRIT;
- break;
- case UA_LOGLEVEL_TRACE:
- default:
- return;
+/**
+ * Join an array of UA_String to a single NULL-Terminated UA_String
+ * separated by character sep
+ */
+static UA_StatusCode
+join_string_with_sep(const UA_String *strings, size_t stringsSize,
+ char sep, UA_String *out) {
+ if(!out)
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+
+ UA_String_clear(out);
+ size_t totalSize = stringsSize;
+ for(size_t iStr = 0; iStr < stringsSize; ++iStr) {
+ totalSize += strings[iStr].length;
}
-#define LOGBUFSIZE 512
- char logbuf[LOGBUFSIZE];
- int pos = snprintf(logbuf, LOGBUFSIZE, "[%s/%s] ",
- syslogLevelNames[level], syslogCategoryNames[category]);
- if(pos < 0) {
- syslog(LOG_WARNING, "Log message too long for syslog");
- return;
+ UA_ByteString_allocBuffer(out, totalSize);
+ if(!out->data) {
+ return UA_STATUSCODE_BADOUTOFMEMORY;
}
- pos = vsnprintf(&logbuf[pos], LOGBUFSIZE - (size_t)pos, msg, args);
- if(pos < 0) {
- syslog(LOG_WARNING, "Log message too long for syslog");
- return;
+
+ size_t pos = 0;
+ for(size_t iStr = 0; iStr < stringsSize; ++iStr) {
+ memcpy(&out->data[pos], strings[iStr].data, strings[iStr].length);
+ pos += strings[iStr].length;
+ out->data[pos] = (UA_Byte) sep;
+ ++pos;
}
+ out->data[out->length-1] = 0;
- syslog(priority, "%s", logbuf);
+ return UA_STATUSCODE_GOOD;
}
-static void
-UA_Log_Syslog_clear(void *logContext) {
- /* closelog is optional. We don't use it as several loggers might be
- * instantiated in parallel. */
- /* closelog(); */
+/**
+ * Search for a character in a string (like strchr).
+ * \todo Handle UTF-8
+ *
+ * \return index of the character or -1 on case of an error.
+ */
+
+static UA_Int32
+UA_String_chr(const UA_String *pUaStr, char needl) {
+ UA_Byte byteNeedl = (UA_Byte)needl;
+ for(size_t i = 0; (size_t)i < pUaStr->length; ++i) {
+ if(pUaStr->data[i] == byteNeedl) {
+ return (UA_Int32) i;
+ }
+ }
+ return -1;
}
-UA_Logger
-UA_Log_Syslog(void) {
- return UA_Log_Syslog_withLevel(UA_LOGLEVEL_TRACE);
+static UA_StatusCode
+add_x509V3ext(X509 *x509, int nid, const char *value) {
+ X509_EXTENSION *ex;
+ X509V3_CTX ctx;
+ X509V3_set_ctx_nodb(&ctx);
+ X509V3_set_ctx(&ctx, x509, x509, NULL, NULL, 0);
+ ex = X509V3_EXT_conf_nid(NULL, &ctx, nid, value);
+ if(!ex)
+ return UA_STATUSCODE_BADINTERNALERROR;
+ X509_add_ext(x509, ex, -1);
+ X509_EXTENSION_free(ex);
+ return UA_STATUSCODE_GOOD;
}
-UA_Logger
-UA_Log_Syslog_withLevel(UA_LogLevel minlevel) {
- UA_Logger logger = {UA_Log_Syslog_log, (void*)minlevel, UA_Log_Syslog_clear};
- return logger;
+#if (OPENSSL_VERSION_NUMBER >= 0x30000000L)
+
+/* generate the RSA key */
+
+static EVP_PKEY * UA_RSA_Generate_Key (size_t keySizeBits){
+ return EVP_RSA_gen(keySizeBits);
}
#endif
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/plugins/securityPolicies/securitypolicy_mbedtls_common.h" ***********************************/
+UA_StatusCode
+UA_CreateCertificate(const UA_Logger *logger,
+ const UA_String *subject, size_t subjectSize,
+ const UA_String *subjectAltName, size_t subjectAltNameSize,
+ size_t keySizeBits, UA_CertificateFormat certFormat,
+ UA_ByteString *outPrivateKey, UA_ByteString *outCertificate) {
+ if(!outPrivateKey || !outCertificate || !logger || !subjectAltName ||
+ !subject || subjectAltNameSize == 0 || subjectSize == 0 ||
+ (certFormat != UA_CERTIFICATEFORMAT_DER && certFormat != UA_CERTIFICATEFORMAT_PEM ))
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
-/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
- * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
- *
- * Copyright 2019 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
- */
+ /* Use the maximum size */
+ if(keySizeBits == 0)
+ keySizeBits = 4096;
+ UA_ByteString_init(outPrivateKey);
+ UA_ByteString_init(outCertificate);
+ UA_String fullAltSubj = UA_STRING_NULL;
+ UA_Int32 serial = 1;
-#ifdef UA_ENABLE_ENCRYPTION_MBEDTLS
+ /** \TODO: Seed Random generator
+ * See: (https://www.openssl.org/docs/man1.1.0/man3/RAND_add.html) */
+ BIO *memCert = NULL;
+ BIO *memPKey = NULL;
-#include <mbedtls/md.h>
-#include <mbedtls/x509_crt.h>
-#include <mbedtls/ctr_drbg.h>
+ UA_StatusCode errRet = UA_STATUSCODE_GOOD;
+
+ X509 *x509 = X509_new();
-#if !defined(MBEDTLS_NO_PLATFORM_ENTROPY)
-#define MBEDTLS_ENTROPY_POLL_METHOD mbedtls_platform_entropy_poll
+#if (OPENSSL_VERSION_NUMBER >= 0x30000000L)
+ EVP_PKEY *pkey = UA_RSA_Generate_Key(keySizeBits);
+ if((pkey == NULL) || (x509 == NULL)) {
+ errRet = UA_STATUSCODE_BADOUTOFMEMORY;
+ goto cleanup;
+ }
#else
-// MBEDTLS_ENTROPY_HARDWARE_ALT should be defined if your hardware does not supportd platform entropy
-#define MBEDTLS_ENTROPY_POLL_METHOD mbedtls_hardware_poll
-#endif
+ BIGNUM *exponent = BN_new();
+ EVP_PKEY *pkey = EVP_PKEY_new();
+ RSA *rsa = RSA_new();
+ if(!pkey || !x509 || !exponent || !rsa) {
+ errRet = UA_STATUSCODE_BADOUTOFMEMORY;
+ goto cleanup;
+ }
-#define UA_SHA1_LENGTH 20
+ UA_LOG_INFO(logger, UA_LOGCATEGORY_SECURECHANNEL,
+ "Create Certificate: Generating RSA key. This may take a while.");
-_UA_BEGIN_DECLS
+ if(BN_set_word(exponent, RSA_F4) != 1) {
+ UA_LOG_ERROR(logger, UA_LOGCATEGORY_SECURECHANNEL,
+ "Create Certificate: Setting RSA exponent failed.");
+ errRet = UA_STATUSCODE_BADINTERNALERROR;
+ goto cleanup;
+ }
-void
-swapBuffers(UA_ByteString *const bufA, UA_ByteString *const bufB);
+ if(RSA_generate_key_ex(rsa, (int) keySizeBits, exponent, NULL) != 1) {
+ UA_LOG_ERROR(logger, UA_LOGCATEGORY_SECURECHANNEL,
+ "Create Certificate: Generating RSA key failed.");
+ errRet = UA_STATUSCODE_BADINTERNALERROR;
+ goto cleanup;
+ }
-void
-mbedtls_hmac(mbedtls_md_context_t *context, const UA_ByteString *key,
- const UA_ByteString *in, unsigned char *out);
+ if(EVP_PKEY_assign_RSA(pkey, rsa) != 1) {
+ UA_LOG_ERROR(logger, UA_LOGCATEGORY_SECURECHANNEL,
+ "Create Certificate: Assign RSA key failed.");
+ errRet = UA_STATUSCODE_BADINTERNALERROR;
+ goto cleanup;
+ }
+ /* rsa will be freed by pkey */
+ rsa = NULL;
-UA_StatusCode
-mbedtls_generateKey(mbedtls_md_context_t *context,
- const UA_ByteString *secret, const UA_ByteString *seed,
- UA_ByteString *out);
+#endif /* end of OPENSSL_VERSION_NUMBER >= 0x30000000L */
-UA_StatusCode
-mbedtls_verifySig_sha1(mbedtls_x509_crt *certificate, const UA_ByteString *message,
- const UA_ByteString *signature);
+ /* x509v3 has version 2
+ * (https://www.openssl.org/docs/man1.1.0/man3/X509_set_version.html) */
+ if(X509_set_version(x509, 2) != 1) {
+ UA_LOG_ERROR(logger, UA_LOGCATEGORY_SECURECHANNEL,
+ "Create Certificate: Setting version failed.");
+ errRet = UA_STATUSCODE_BADINTERNALERROR;
+ goto cleanup;
+ }
-UA_StatusCode
-mbedtls_sign_sha1(mbedtls_pk_context *localPrivateKey,
- mbedtls_ctr_drbg_context *drbgContext,
- const UA_ByteString *message,
- UA_ByteString *signature);
+ if(ASN1_INTEGER_set(X509_get_serialNumber(x509), serial) != 1) {
+ UA_LOG_ERROR(logger, UA_LOGCATEGORY_SECURECHANNEL,
+ "Create Certificate: Setting serial number failed.");
+ /* Only memory errors are possible */
+ errRet = UA_STATUSCODE_BADOUTOFMEMORY;
+ goto cleanup;
+ }
-UA_StatusCode
-mbedtls_thumbprint_sha1(const UA_ByteString *certificate,
- UA_ByteString *thumbprint);
+ if(X509_gmtime_adj(X509_get_notBefore(x509), 0) == NULL) {
+ UA_LOG_ERROR(logger, UA_LOGCATEGORY_SECURECHANNEL,
+ "Create Certificate: Setting 'not before' failed.");
+ errRet = UA_STATUSCODE_BADINTERNALERROR;
+ goto cleanup;
+ }
-/* Set the hashing scheme before calling
- * E.g. mbedtls_rsa_set_padding(context, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA1); */
-UA_StatusCode
-mbedtls_encrypt_rsaOaep(mbedtls_rsa_context *context,
- mbedtls_ctr_drbg_context *drbgContext,
- UA_ByteString *data, const size_t plainTextBlockSize);
+ if(X509_gmtime_adj(X509_get_notAfter(x509), (UA_Int64) 60 * 60 * 24 * 365) == NULL) {
+ UA_LOG_ERROR(logger, UA_LOGCATEGORY_SECURECHANNEL,
+ "Create Certificate: Setting 'not before' failed.");
+ errRet = UA_STATUSCODE_BADINTERNALERROR;
+ goto cleanup;
+ }
-UA_StatusCode
-mbedtls_decrypt_rsaOaep(mbedtls_pk_context *localPrivateKey,
- mbedtls_ctr_drbg_context *drbgContext,
- UA_ByteString *data);
+ if(X509_set_pubkey(x509, pkey) != 1) {
+ UA_LOG_ERROR(logger, UA_LOGCATEGORY_SECURECHANNEL,
+ "Create Certificate: Setting publik key failed.");
+ errRet = UA_STATUSCODE_BADINTERNALERROR;
+ goto cleanup;
+ }
-int UA_mbedTLS_LoadPrivateKey(const UA_ByteString *key, mbedtls_pk_context *target);
+ X509_NAME *name = X509_get_subject_name(x509);
+ if(name == NULL) {
+ UA_LOG_ERROR(logger, UA_LOGCATEGORY_SECURECHANNEL,
+ "Create Certificate: Getting name failed.");
+ errRet = UA_STATUSCODE_BADINTERNALERROR;
+ goto cleanup;
+ }
-UA_StatusCode UA_mbedTLS_LoadLocalCertificate(const UA_ByteString *certData, UA_ByteString *target);
+ for(UA_UInt32 iSubject = 0; iSubject < subjectSize; ++iSubject) {
+ UA_Int32 sep = UA_String_chr(&subject[iSubject], '=');
+ char field[16];
+ if(sep == -1 || sep == 0 ||
+ ((size_t) sep == (subject[iSubject].length - 1)) || sep >= 15) {
+ UA_LOG_ERROR(logger, UA_LOGCATEGORY_SECURECHANNEL,
+ "Create Certificate: Subject must contain one '=' with "
+ "content before and after.");
+ errRet = UA_STATUSCODE_BADINTERNALERROR;
+ goto cleanup;
+ }
+ memcpy(field, subject[iSubject].data, (size_t) sep);
+ field[sep] = 0;
+ UA_Byte* pData = &subject[iSubject].data[sep + 1];
+ if(X509_NAME_add_entry_by_txt(
+ name, field, MBSTRING_ASC,
+ (const unsigned char *)pData,
+ (int) subject[iSubject].length - (int) sep - 1, -1, 0) != 1) {
+ UA_LOG_ERROR(logger, UA_LOGCATEGORY_SECURECHANNEL,
+ "Create Certificate: Setting subject failed.");
+ errRet = UA_STATUSCODE_BADINTERNALERROR;
+ goto cleanup;
+ }
+ }
+ /* Self signed, so issuer == subject */
+ if(X509_set_issuer_name(x509, name) != 1) {
+ UA_LOG_ERROR(logger, UA_LOGCATEGORY_SECURECHANNEL,
+ "Create Certificate: Setting name failed.");
+ errRet = UA_STATUSCODE_BADINTERNALERROR;
+ goto cleanup;
+ }
-UA_ByteString UA_mbedTLS_CopyDataFormatAware(const UA_ByteString *data);
+ errRet = add_x509V3ext(x509, NID_basic_constraints, "CA:FALSE");
+ if(errRet != UA_STATUSCODE_GOOD) {
+ UA_LOG_ERROR(logger, UA_LOGCATEGORY_SECURECHANNEL,
+ "Create Certificate: Setting 'Basic Constraints' failed.");
+ goto cleanup;
+ }
-_UA_END_DECLS
+ /* See https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.3 for
+ * possible values */
+ errRet = add_x509V3ext(x509, NID_key_usage,
+ "digitalSignature,nonRepudiation,keyEncipherment,dataEncipherment,keyCertSign");
+ if(errRet != UA_STATUSCODE_GOOD) {
+ UA_LOG_ERROR(logger, UA_LOGCATEGORY_SECURECHANNEL,
+ "Create Certificate: Setting 'Key Usage' failed.");
+ goto cleanup;
+ }
+
+ errRet = add_x509V3ext(x509, NID_ext_key_usage, "serverAuth,clientAuth");
+ if(errRet != UA_STATUSCODE_GOOD) {
+ UA_LOG_ERROR(logger, UA_LOGCATEGORY_SECURECHANNEL,
+ "Create Certificate: Setting 'Extended Key Usage' failed.");
+ goto cleanup;
+ }
+
+ errRet = add_x509V3ext(x509, NID_subject_key_identifier, "hash");
+ if(errRet != UA_STATUSCODE_GOOD) {
+ UA_LOG_ERROR(logger, UA_LOGCATEGORY_SECURECHANNEL,
+ "Create Certificate: Setting 'Subject Key Identifier' failed.");
+ goto cleanup;
+ }
+
+ errRet = join_string_with_sep(subjectAltName, subjectAltNameSize, ',', &fullAltSubj);
+ if(errRet != UA_STATUSCODE_GOOD) {
+ UA_LOG_ERROR(logger, UA_LOGCATEGORY_SECURECHANNEL,
+ "Create Certificate: Joining altSubject failed.");
+ goto cleanup;
+ }
+
+ errRet = add_x509V3ext(x509, NID_subject_alt_name, (const char*) fullAltSubj.data);
+ if(errRet != UA_STATUSCODE_GOOD) {
+ UA_LOG_ERROR(logger, UA_LOGCATEGORY_SECURECHANNEL,
+ "Create Certificate: Setting 'Subject Alternative Name:' failed.");
+ goto cleanup;
+ }
+
+ if(X509_sign(x509, pkey, EVP_sha256()) == 0) {
+ UA_LOG_ERROR(logger, UA_LOGCATEGORY_SECURECHANNEL,
+ "Create Certificate: Signing failed.");
+ errRet = UA_STATUSCODE_BADINTERNALERROR;
+ goto cleanup;
+ }
+
+ switch(certFormat) {
+ case UA_CERTIFICATEFORMAT_DER: {
+ int tmpLen = i2d_PrivateKey(pkey, &outPrivateKey->data);
+ if(tmpLen <= 0) {
+ UA_LOG_ERROR(logger, UA_LOGCATEGORY_SECURECHANNEL,
+ "Create Certificate: Create private DER key failed.");
+ errRet = UA_STATUSCODE_BADINTERNALERROR;
+ goto cleanup;
+ }
+ outPrivateKey->length = (size_t) tmpLen;
+ tmpLen = i2d_X509(x509, &outCertificate->data);
+ if(tmpLen <= 0) {
+ UA_LOG_ERROR(logger, UA_LOGCATEGORY_SECURECHANNEL,
+ "Create Certificate: Create DER-certificate failed.");
+ errRet = UA_STATUSCODE_BADINTERNALERROR;
+ goto cleanup;
+ }
+ outCertificate->length = (size_t) tmpLen;
+ break;
+ }
+ case UA_CERTIFICATEFORMAT_PEM: {
+ /* Private Key */
+ memPKey = BIO_new(BIO_s_mem());
+ if(!memPKey) {
+ UA_LOG_ERROR(logger, UA_LOGCATEGORY_SECURECHANNEL,
+ "Create Certificate: Allocate Membuffer for PKey failed.");
+ errRet = UA_STATUSCODE_BADOUTOFMEMORY;
+ goto cleanup;
+ }
+
+ if(PEM_write_bio_PrivateKey(memPKey, pkey, NULL, NULL, 0, 0, NULL) != 1) {
+ UA_LOG_ERROR(logger, UA_LOGCATEGORY_SECURECHANNEL,
+ "Create Certificate: Generate PEM-PrivateKey failed.");
+ errRet = UA_STATUSCODE_BADINTERNALERROR;
+ goto cleanup;
+ }
+
+ UA_ByteString tmpPem = UA_BYTESTRING_NULL;
+ tmpPem.length = (size_t) BIO_get_mem_data(memPKey, &tmpPem.data);
+ errRet = UA_ByteString_copy(&tmpPem, outPrivateKey);
+ if(errRet != UA_STATUSCODE_GOOD) {
+ UA_LOG_ERROR(logger, UA_LOGCATEGORY_SECURECHANNEL,
+ "Create Certificate: Copy PEM PKey failed.");
+ goto cleanup;
+ }
+
+ /* Certificate */
+ memCert = BIO_new(BIO_s_mem());
+ if(!memCert) {
+ UA_LOG_ERROR(logger, UA_LOGCATEGORY_SECURECHANNEL,
+ "Create Certificate: Allocate Membuffer for Cert failed.");
+ errRet = UA_STATUSCODE_BADOUTOFMEMORY;
+ goto cleanup;
+ }
+
+ if(PEM_write_bio_X509(memCert, x509) != 1) {
+ UA_LOG_ERROR(logger, UA_LOGCATEGORY_SECURECHANNEL,
+ "Create Certificate: Generate PEM-Certifcate failed.");
+ errRet = UA_STATUSCODE_BADINTERNALERROR;
+ goto cleanup;
+ }
+
+ tmpPem.length = (size_t) BIO_get_mem_data(memCert, &tmpPem.data);
+ errRet = UA_ByteString_copy(&tmpPem, outCertificate);
+ if(errRet != UA_STATUSCODE_GOOD) {
+ UA_LOG_ERROR(logger, UA_LOGCATEGORY_SECURECHANNEL,
+ "Create Certificate: Copy PEM Certificate failed.");
+ goto cleanup;
+ }
+ break;
+ }
+ }
+
+cleanup:
+ UA_String_clear(&fullAltSubj);
+#if (OPENSSL_VERSION_NUMBER < 0x30000000L)
+ RSA_free(rsa);
+ BN_free(exponent);
#endif
+ X509_free(x509);
+ EVP_PKEY_free(pkey);
+ BIO_free(memCert);
+ BIO_free(memPKey);
+ return errRet;
+}
+#endif
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/plugins/securityPolicies/securitypolicy_mbedtls_common.c" ***********************************/
+/**** amalgamated original file "/plugins/crypto/openssl/ua_pki_openssl.c" ****/
+/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
+ * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
+ *
+ * Copyright 2020 (c) Wind River Systems, Inc.
+ * Copyright 2020 (c) basysKom GmbH
-#ifdef UA_ENABLE_ENCRYPTION_MBEDTLS
+ */
-#include <mbedtls/aes.h>
-#include <mbedtls/ctr_drbg.h>
-#include <mbedtls/entropy.h>
-#include <mbedtls/entropy_poll.h>
-#include <mbedtls/error.h>
-#include <mbedtls/md.h>
-#include <mbedtls/sha1.h>
-#include <mbedtls/version.h>
-#include <mbedtls/x509_crt.h>
-void
-swapBuffers(UA_ByteString *const bufA, UA_ByteString *const bufB) {
- UA_ByteString tmp = *bufA;
- *bufA = *bufB;
- *bufB = tmp;
+#if defined(UA_ENABLE_ENCRYPTION_OPENSSL) || defined(UA_ENABLE_ENCRYPTION_LIBRESSL)
+#include <openssl/x509.h>
+#include <openssl/x509_vfy.h>
+#include <openssl/x509v3.h>
+#include <openssl/pem.h>
+
+
+/* Find binary substring. Taken and adjusted from
+ * http://tungchingkai.blogspot.com/2011/07/binary-strstr.html */
+
+static const unsigned char *
+bstrchr(const unsigned char *s, const unsigned char ch, size_t l) {
+ /* find first occurrence of c in char s[] for length l*/
+ for(; l > 0; ++s, --l) {
+ if(*s == ch)
+ return s;
+ }
+ return NULL;
}
-void
-mbedtls_hmac(mbedtls_md_context_t *context, const UA_ByteString *key,
- const UA_ByteString *in, unsigned char *out) {
- mbedtls_md_hmac_starts(context, key->data, key->length);
- mbedtls_md_hmac_update(context, in->data, in->length);
- mbedtls_md_hmac_finish(context, out);
+static const unsigned char *
+UA_Bstrstr(const unsigned char *s1, size_t l1, const unsigned char *s2, size_t l2) {
+ /* find first occurrence of s2[] in s1[] for length l1*/
+ const unsigned char *ss1 = s1;
+ const unsigned char *ss2 = s2;
+ /* handle special case */
+ if(l1 == 0)
+ return (NULL);
+ if(l2 == 0)
+ return s1;
+
+ /* match prefix */
+ for (; (s1 = bstrchr(s1, *s2, (uintptr_t)ss1-(uintptr_t)s1+(uintptr_t)l1)) != NULL &&
+ (uintptr_t)ss1-(uintptr_t)s1+(uintptr_t)l1 != 0; ++s1) {
+
+ /* match rest of prefix */
+ const unsigned char *sc1, *sc2;
+ for (sc1 = s1, sc2 = s2; ;)
+ if (++sc2 >= ss2+l2)
+ return s1;
+ else if (*++sc1 != *sc2)
+ break;
+ }
+ return NULL;
}
-UA_StatusCode
-mbedtls_generateKey(mbedtls_md_context_t *context,
- const UA_ByteString *secret, const UA_ByteString *seed,
- UA_ByteString *out) {
- size_t hashLen = (size_t)mbedtls_md_get_size(context->md_info);
+typedef struct {
+ /*
+ * If the folders are defined, we use them to reload the certificates during
+ * runtime
+ */
- UA_ByteString A_and_seed;
- UA_ByteString_allocBuffer(&A_and_seed, hashLen + seed->length);
- memcpy(A_and_seed.data + hashLen, seed->data, seed->length);
+ UA_String trustListFolder;
+ UA_String issuerListFolder;
+ UA_String revocationListFolder;
- UA_ByteString ANext_and_seed;
- UA_ByteString_allocBuffer(&ANext_and_seed, hashLen + seed->length);
- memcpy(ANext_and_seed.data + hashLen, seed->data, seed->length);
+ STACK_OF(X509) * skIssue;
+ STACK_OF(X509) * skTrusted;
+ STACK_OF(X509_CRL) * skCrls; /* Revocation list*/
+} CertContext;
- UA_ByteString A = {
- hashLen,
- A_and_seed.data
- };
+static UA_StatusCode
+UA_CertContext_sk_Init (CertContext * context) {
+ context->skTrusted = sk_X509_new_null();
+ context->skIssue = sk_X509_new_null();
+ context->skCrls = sk_X509_CRL_new_null();
+ if (context->skTrusted == NULL || context->skIssue == NULL ||
+ context->skCrls == NULL) {
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ }
+ return UA_STATUSCODE_GOOD;
+}
- UA_ByteString ANext = {
- hashLen,
- ANext_and_seed.data
- };
+static void
+UA_CertContext_sk_free (CertContext * context) {
+ sk_X509_pop_free (context->skTrusted, X509_free);
+ sk_X509_pop_free (context->skIssue, X509_free);
+ sk_X509_CRL_pop_free (context->skCrls, X509_CRL_free);
+}
- mbedtls_hmac(context, secret, seed, A.data);
+static UA_StatusCode
+UA_CertContext_Init (CertContext * context) {
+ (void) memset (context, 0, sizeof (CertContext));
+ UA_ByteString_init (&context->trustListFolder);
+ UA_ByteString_init (&context->issuerListFolder);
+ UA_ByteString_init (&context->revocationListFolder);
+ return UA_CertContext_sk_Init (context);
+}
- UA_StatusCode retval = 0;
- for(size_t offset = 0; offset < out->length; offset += hashLen) {
- UA_ByteString outSegment = {
- hashLen,
- out->data + offset
- };
- UA_Boolean bufferAllocated = UA_FALSE;
- // Not enough room in out buffer to write the hash.
- if(offset + hashLen > out->length) {
- outSegment.data = NULL;
- outSegment.length = 0;
- retval = UA_ByteString_allocBuffer(&outSegment, hashLen);
- if(retval != UA_STATUSCODE_GOOD) {
- UA_ByteString_deleteMembers(&A_and_seed);
- UA_ByteString_deleteMembers(&ANext_and_seed);
- return retval;
- }
- bufferAllocated = UA_TRUE;
+static void
+UA_CertificateVerification_clear (UA_CertificateVerification * cv) {
+ if (cv == NULL) {
+ return ;
+ }
+ CertContext * context = (CertContext *) cv->context;
+ if (context == NULL) {
+ return;
+ }
+ UA_ByteString_clear (&context->trustListFolder);
+ UA_ByteString_clear (&context->issuerListFolder);
+ UA_ByteString_clear (&context->revocationListFolder);
+
+ UA_CertContext_sk_free (context);
+ UA_free (context);
+
+ cv->context = NULL;
+
+ return;
+}
+
+static UA_StatusCode
+UA_skTrusted_Cert2X509 (const UA_ByteString * certificateTrustList,
+ size_t certificateTrustListSize,
+ CertContext * ctx) {
+ size_t i;
+
+ for (i = 0; i < certificateTrustListSize; i++) {
+ X509 * x509 = UA_OpenSSL_LoadCertificate(&certificateTrustList[i]);
+
+ if (x509 == NULL) {
+ return UA_STATUSCODE_BADINTERNALERROR;
}
+ sk_X509_push (ctx->skTrusted, x509);
+ }
- mbedtls_hmac(context, secret, &A_and_seed, outSegment.data);
- mbedtls_hmac(context, secret, &A, ANext.data);
+ return UA_STATUSCODE_GOOD;
+}
- if(retval != UA_STATUSCODE_GOOD) {
- if(bufferAllocated)
- UA_ByteString_deleteMembers(&outSegment);
- UA_ByteString_deleteMembers(&A_and_seed);
- UA_ByteString_deleteMembers(&ANext_and_seed);
- return retval;
+static UA_StatusCode
+UA_skIssuer_Cert2X509 (const UA_ByteString * certificateIssuerList,
+ size_t certificateIssuerListSize,
+ CertContext * ctx) {
+ size_t i;
+
+ for (i = 0; i < certificateIssuerListSize; i++) {
+ X509 * x509 = UA_OpenSSL_LoadCertificate(&certificateIssuerList[i]);
+
+ if (x509 == NULL) {
+ return UA_STATUSCODE_BADINTERNALERROR;
}
+ sk_X509_push (ctx->skIssue, x509);
+ }
- if(bufferAllocated) {
- memcpy(out->data + offset, outSegment.data, out->length - offset);
- UA_ByteString_deleteMembers(&outSegment);
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_StatusCode
+UA_skCrls_Cert2X509 (const UA_ByteString * certificateRevocationList,
+ size_t certificateRevocationListSize,
+ CertContext * ctx) {
+ size_t i;
+ const unsigned char * pData;
+
+ for (i = 0; i < certificateRevocationListSize; i++) {
+ pData = certificateRevocationList[i].data;
+ X509_CRL * crl = NULL;
+
+ if (certificateRevocationList[i].length > 1 && pData[0] == 0x30 && pData[1] == 0x82) { // Magic number for DER encoded files
+ crl = d2i_X509_CRL (NULL, &pData, (long) certificateRevocationList[i].length);
+ } else {
+ BIO* bio = NULL;
+ bio = BIO_new_mem_buf((void *) certificateRevocationList[i].data,
+ (int) certificateRevocationList[i].length);
+ crl = PEM_read_bio_X509_CRL(bio, NULL, NULL, NULL);
+ BIO_free(bio);
}
- swapBuffers(&ANext_and_seed, &A_and_seed);
- swapBuffers(&ANext, &A);
+ if (crl == NULL) {
+ return UA_STATUSCODE_BADINTERNALERROR;
+ }
+ sk_X509_CRL_push (ctx->skCrls, crl);
}
- UA_ByteString_deleteMembers(&A_and_seed);
- UA_ByteString_deleteMembers(&ANext_and_seed);
- return UA_STATUSCODE_GOOD;
+ return UA_STATUSCODE_GOOD;
}
-UA_StatusCode
-mbedtls_verifySig_sha1(mbedtls_x509_crt *certificate, const UA_ByteString *message,
- const UA_ByteString *signature) {
- /* Compute the sha1 hash */
- unsigned char hash[UA_SHA1_LENGTH];
-#if MBEDTLS_VERSION_NUMBER >= 0x02070000
- mbedtls_sha1_ret(message->data, message->length, hash);
-#else
- mbedtls_sha1(message->data, message->length, hash);
-#endif
+#ifdef __linux__
+#include <dirent.h>
- /* Set the RSA settings */
- mbedtls_rsa_context *rsaContext = mbedtls_pk_rsa(certificate->pk);
- if(!rsaContext)
- return UA_STATUSCODE_BADINTERNALERROR;
- mbedtls_rsa_set_padding(rsaContext, MBEDTLS_RSA_PKCS_V15, 0);
+static int UA_Certificate_Filter_der_pem (const struct dirent * entry) {
+ /* ignore hidden files */
+ if (entry->d_name[0] == '.') return 0;
- /* Verify */
- int mbedErr = mbedtls_pk_verify(&certificate->pk,
- MBEDTLS_MD_SHA1, hash, UA_SHA1_LENGTH,
- signature->data, signature->length);
- if(mbedErr)
- return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
- return UA_STATUSCODE_GOOD;
+ /* check file extension */
+ const char *pszFind = strrchr(entry->d_name, '.');
+ if (pszFind == 0)
+ return 0;
+ pszFind++;
+ if (strcmp (pszFind, "der") == 0 || strcmp (pszFind, "pem") == 0)
+ return 1;
+
+ return 0;
}
-UA_StatusCode
-mbedtls_sign_sha1(mbedtls_pk_context *localPrivateKey,
- mbedtls_ctr_drbg_context *drbgContext,
- const UA_ByteString *message,
- UA_ByteString *signature) {
- unsigned char hash[UA_SHA1_LENGTH];
-#if MBEDTLS_VERSION_NUMBER >= 0x02070000
- mbedtls_sha1_ret(message->data, message->length, hash);
-#else
- mbedtls_sha1(message->data, message->length, hash);
-#endif
+static int UA_Certificate_Filter_crl (const struct dirent * entry) {
- mbedtls_rsa_context *rsaContext = mbedtls_pk_rsa(*localPrivateKey);
- mbedtls_rsa_set_padding(rsaContext, MBEDTLS_RSA_PKCS_V15, 0);
+ /* ignore hidden files */
+ if (entry->d_name[0] == '.') return 0;
+
+ /* check file extension */
+ const char *pszFind = strrchr(entry->d_name, '.');
+ if (pszFind == 0)
+ return 0;
+ pszFind++;
+ if (strcmp (pszFind, "crl") == 0)
+ return 1;
+
+ return 0;
+}
+
+static UA_StatusCode
+UA_BuildFullPath (const char * path,
+ const char * fileName,
+ size_t fullPathBufferLength,
+ char * fullPath) {
+ size_t pathLen = strlen (path);
+ size_t fileNameLen = strlen (fileName);
+ if ((pathLen + fileNameLen + 2) > fullPathBufferLength) {
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+ }
+ strcpy (fullPath, path);
+ strcat (fullPath, "/");
+ strcat (fullPath, fileName);
- size_t sigLen = 0;
- int mbedErr = mbedtls_pk_sign(localPrivateKey, MBEDTLS_MD_SHA1, hash,
- UA_SHA1_LENGTH, signature->data, &sigLen,
- mbedtls_ctr_drbg_random, drbgContext);
- if(mbedErr)
- return UA_STATUSCODE_BADINTERNALERROR;
return UA_STATUSCODE_GOOD;
}
-UA_StatusCode
-mbedtls_thumbprint_sha1(const UA_ByteString *certificate,
- UA_ByteString *thumbprint) {
- if(UA_ByteString_equal(certificate, &UA_BYTESTRING_NULL))
- return UA_STATUSCODE_BADINTERNALERROR;
+static UA_StatusCode
+UA_loadCertFromFile (const char * fileName,
+ UA_ByteString * cert) {
+
+ FILE * fp = fopen(fileName, "rb");
- if(thumbprint->length != UA_SHA1_LENGTH)
+ if (fp == NULL)
return UA_STATUSCODE_BADINTERNALERROR;
+
+ fseek(fp, 0, SEEK_END);
+ cert->length = (size_t) ftell(fp);
+ if (UA_ByteString_allocBuffer (cert, cert->length) != UA_STATUSCODE_GOOD) {
+ fclose (fp);
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ }
+ fseek(fp, 0, SEEK_SET);
+ size_t readLen = fread (cert->data, 1, cert->length, fp);
+ if (readLen != cert->length) {
+ UA_ByteString_clear (cert);
+ cert->length = 0;
+ fclose (fp);
+ return UA_STATUSCODE_BADINTERNALERROR;
+ }
+ fclose (fp);
- /* The certificate thumbprint is always a 20 bit sha1 hash, see Part 4 of the Specification. */
-#if MBEDTLS_VERSION_NUMBER >= 0x02070000
- mbedtls_sha1_ret(certificate->data, certificate->length, thumbprint->data);
-#else
- mbedtls_sha1(certificate->data, certificate->length, thumbprint->data);
-#endif
return UA_STATUSCODE_GOOD;
}
-UA_StatusCode
-mbedtls_encrypt_rsaOaep(mbedtls_rsa_context *context,
- mbedtls_ctr_drbg_context *drbgContext,
- UA_ByteString *data, const size_t plainTextBlockSize) {
- if(data->length % plainTextBlockSize != 0)
- return UA_STATUSCODE_BADINTERNALERROR;
+static UA_StatusCode
+UA_ReloadCertFromFolder (CertContext * ctx) {
+ UA_StatusCode ret;
+ struct dirent ** dirlist = NULL;
+ int i;
+ int numCertificates;
+ char certFile[PATH_MAX];
+ UA_ByteString strCert;
+ char folderPath[PATH_MAX];
- size_t max_blocks = data->length / plainTextBlockSize;
+ UA_ByteString_init (&strCert);
- UA_ByteString encrypted;
- UA_StatusCode retval = UA_ByteString_allocBuffer(&encrypted, max_blocks * context->len);
- if(retval != UA_STATUSCODE_GOOD)
- return retval;
+ if (ctx->trustListFolder.length > 0) {
+ UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "Reloading the trust-list");
- size_t lenDataToEncrypt = data->length;
- size_t inOffset = 0;
- size_t offset = 0;
- const unsigned char *label = NULL;
- while(lenDataToEncrypt >= plainTextBlockSize) {
- int mbedErr = mbedtls_rsa_rsaes_oaep_encrypt(context, mbedtls_ctr_drbg_random,
- drbgContext, MBEDTLS_RSA_PUBLIC,
- label, 0, plainTextBlockSize,
- data->data + inOffset, encrypted.data + offset);
- if(mbedErr) {
- UA_ByteString_deleteMembers(&encrypted);
- return UA_STATUSCODE_BADINTERNALERROR;
+ sk_X509_pop_free (ctx->skTrusted, X509_free);
+ ctx->skTrusted = sk_X509_new_null();
+ if (ctx->skTrusted == NULL) {
+ return UA_STATUSCODE_BADOUTOFMEMORY;
}
- inOffset += plainTextBlockSize;
- offset += context->len;
- lenDataToEncrypt -= plainTextBlockSize;
+ (void) memcpy (folderPath, ctx->trustListFolder.data,
+ ctx->trustListFolder.length);
+ folderPath[ctx->trustListFolder.length] = 0;
+ numCertificates = scandir(folderPath, &dirlist,
+ UA_Certificate_Filter_der_pem,
+ alphasort);
+ for (i = 0; i < numCertificates; i++) {
+ if (UA_BuildFullPath (folderPath, dirlist[i]->d_name,
+ PATH_MAX, certFile) != UA_STATUSCODE_GOOD) {
+ continue;
+ }
+ ret = UA_loadCertFromFile (certFile, &strCert);
+ if (ret != UA_STATUSCODE_GOOD) {
+ UA_LOG_INFO (UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
+ "Failed to load the certificate file %s", certFile);
+ continue; /* continue or return ? */
+ }
+ if (UA_skTrusted_Cert2X509 (&strCert, 1, ctx) != UA_STATUSCODE_GOOD) {
+ UA_LOG_INFO (UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
+ "Failed to decode the certificate file %s", certFile);
+ UA_ByteString_clear (&strCert);
+ continue; /* continue or return ? */
+ }
+ UA_ByteString_clear (&strCert);
+ }
}
- memcpy(data->data, encrypted.data, offset);
- UA_ByteString_deleteMembers(&encrypted);
- return UA_STATUSCODE_GOOD;
+ if (ctx->issuerListFolder.length > 0) {
+ UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "Reloading the issuer-list");
+
+ sk_X509_pop_free (ctx->skIssue, X509_free);
+ ctx->skIssue = sk_X509_new_null();
+ if (ctx->skIssue == NULL) {
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ }
+
+ memcpy (folderPath, ctx->issuerListFolder.data, ctx->issuerListFolder.length);
+ folderPath[ctx->issuerListFolder.length] = 0;
+ numCertificates = scandir(folderPath, &dirlist,
+ UA_Certificate_Filter_der_pem,
+ alphasort);
+ for (i = 0; i < numCertificates; i++) {
+ if (UA_BuildFullPath (folderPath, dirlist[i]->d_name,
+ PATH_MAX, certFile) != UA_STATUSCODE_GOOD) {
+ continue;
+ }
+ ret = UA_loadCertFromFile (certFile, &strCert);
+ if (ret != UA_STATUSCODE_GOOD) {
+ UA_LOG_INFO (UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
+ "Failed to load the certificate file %s", certFile);
+ continue; /* continue or return ? */
+ }
+ if (UA_skIssuer_Cert2X509 (&strCert, 1, ctx) != UA_STATUSCODE_GOOD) {
+ UA_LOG_INFO (UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
+ "Failed to decode the certificate file %s", certFile);
+ UA_ByteString_clear (&strCert);
+ continue; /* continue or return ? */
+ }
+ UA_ByteString_clear (&strCert);
+ }
+ }
+
+ if (ctx->revocationListFolder.length > 0) {
+ UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "Reloading the revocation-list");
+
+ sk_X509_CRL_pop_free (ctx->skCrls, X509_CRL_free);
+ ctx->skCrls = sk_X509_CRL_new_null();
+ if (ctx->skCrls == NULL) {
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ }
+
+ memcpy (folderPath, ctx->revocationListFolder.data, ctx->revocationListFolder.length);
+ folderPath[ctx->revocationListFolder.length] = 0;
+ numCertificates = scandir(folderPath, &dirlist,
+ UA_Certificate_Filter_crl,
+ alphasort);
+ for (i = 0; i < numCertificates; i++) {
+ if (UA_BuildFullPath (folderPath, dirlist[i]->d_name,
+ PATH_MAX, certFile) != UA_STATUSCODE_GOOD) {
+ continue;
+ }
+ ret = UA_loadCertFromFile (certFile, &strCert);
+ if (ret != UA_STATUSCODE_GOOD) {
+ UA_LOG_INFO (UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
+ "Failed to load the revocation file %s", certFile);
+ continue; /* continue or return ? */
+ }
+ if (UA_skCrls_Cert2X509 (&strCert, 1, ctx) != UA_STATUSCODE_GOOD) {
+ UA_LOG_INFO (UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
+ "Failed to decode the revocation file %s", certFile);
+ UA_ByteString_clear (&strCert);
+ continue; /* continue or return ? */
+ }
+ UA_ByteString_clear (&strCert);
+ }
+ }
+
+ ret = UA_STATUSCODE_GOOD;
+ return ret;
}
-UA_StatusCode
-mbedtls_decrypt_rsaOaep(mbedtls_pk_context *localPrivateKey,
- mbedtls_ctr_drbg_context *drbgContext,
- UA_ByteString *data) {
- mbedtls_rsa_context *rsaContext = mbedtls_pk_rsa(*localPrivateKey);
- mbedtls_rsa_set_padding(rsaContext, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA1);
+#endif /* end of __linux__ */
- if(data->length % rsaContext->len != 0)
+static UA_StatusCode
+UA_X509_Store_CTX_Error_To_UAError (int opensslErr) {
+ UA_StatusCode ret;
+
+ switch (opensslErr) {
+ case X509_V_ERR_CERT_HAS_EXPIRED:
+ case X509_V_ERR_CERT_NOT_YET_VALID:
+ case X509_V_ERR_CRL_NOT_YET_VALID:
+ case X509_V_ERR_CRL_HAS_EXPIRED:
+ case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
+ case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
+ case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD:
+ case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD:
+ ret = UA_STATUSCODE_BADCERTIFICATETIMEINVALID;
+ break;
+ case X509_V_ERR_CERT_REVOKED:
+ ret = UA_STATUSCODE_BADCERTIFICATEREVOKED;
+ break;
+ case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
+ case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
+ case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
+ ret = UA_STATUSCODE_BADCERTIFICATEUNTRUSTED;
+ break;
+ case X509_V_ERR_CERT_SIGNATURE_FAILURE:
+ case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
+ ret = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
+ break;
+ case X509_V_ERR_UNABLE_TO_GET_CRL:
+ ret = UA_STATUSCODE_BADCERTIFICATEREVOCATIONUNKNOWN;
+ break;
+ default:
+ ret = UA_STATUSCODE_BADCERTIFICATEINVALID;
+ break;
+ }
+ return ret;
+ }
+
+static UA_StatusCode
+UA_CertificateVerification_Verify (void * verificationContext,
+ const UA_ByteString * certificate) {
+ X509_STORE_CTX* storeCtx;
+ X509_STORE* store;
+ CertContext * ctx;
+ UA_StatusCode ret;
+ int opensslRet;
+ X509 * certificateX509 = NULL;
+
+ if (verificationContext == NULL) {
return UA_STATUSCODE_BADINTERNALERROR;
+ }
+ ctx = (CertContext *) verificationContext;
+
+ store = X509_STORE_new();
+ storeCtx = X509_STORE_CTX_new();
+
+ if (store == NULL || storeCtx == NULL) {
+ ret = UA_STATUSCODE_BADOUTOFMEMORY;
+ goto cleanup;
+ }
+#ifdef __linux__
+ ret = UA_ReloadCertFromFolder (ctx);
+ if (ret != UA_STATUSCODE_GOOD) {
+ goto cleanup;
+ }
+#endif
- size_t inOffset = 0;
- size_t outOffset = 0;
- size_t outLength = 0;
- unsigned char buf[512];
+ certificateX509 = UA_OpenSSL_LoadCertificate(certificate);
+ if (certificateX509 == NULL) {
+ ret = UA_STATUSCODE_BADCERTIFICATEINVALID;
+ goto cleanup;
+ }
- while(inOffset < data->length) {
- int mbedErr = mbedtls_rsa_rsaes_oaep_decrypt(rsaContext, mbedtls_ctr_drbg_random,
- drbgContext, MBEDTLS_RSA_PRIVATE,
- NULL, 0, &outLength,
- data->data + inOffset,
- buf, 512);
- if(mbedErr)
- return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
+ X509_STORE_set_flags(store, 0);
+ opensslRet = X509_STORE_CTX_init (storeCtx, store, certificateX509,
+ ctx->skIssue);
+ if (opensslRet != 1) {
+ ret = UA_STATUSCODE_BADINTERNALERROR;
+ goto cleanup;
+ }
- memcpy(data->data + outOffset, buf, outLength);
- inOffset += rsaContext->len;
- outOffset += outLength;
+ (void) X509_STORE_CTX_set0_trusted_stack (storeCtx, ctx->skTrusted);
+
+
+ /* Set crls to ctx */
+ if (sk_X509_CRL_num (ctx->skCrls) > 0) {
+ X509_STORE_CTX_set0_crls (storeCtx, ctx->skCrls);
}
- data->length = outOffset;
+ /* Set flag to check if the certificate has an invalid signature */
+ X509_STORE_CTX_set_flags (storeCtx, X509_V_FLAG_CHECK_SS_SIGNATURE);
+
+ if (X509_STORE_CTX_get_check_issued(storeCtx) (storeCtx,certificateX509, certificateX509) != 1) {
+ X509_STORE_CTX_set_flags (storeCtx, X509_V_FLAG_CRL_CHECK);
+ }
+
+ /* This condition will check whether the certificate is a User certificate or a CA certificate.
+ * If the KU_KEY_CERT_SIGN and KU_CRL_SIGN of key_usage are set, then the certificate shall be
+ * condidered as CA Certificate and cannot be used to establish a connection. Refer the test case
+ * CTT/Security/Security Certificate Validation/029.js for more details */
+ /** \todo Can the ca-parameter of X509_check_purpose can be used? */
+ if(X509_check_purpose(certificateX509, X509_PURPOSE_CRL_SIGN, 0) && X509_check_ca(certificateX509)) {
+ return UA_STATUSCODE_BADCERTIFICATEUSENOTALLOWED;
+ }
+
+ opensslRet = X509_verify_cert (storeCtx);
+ if (opensslRet == 1) {
+ ret = UA_STATUSCODE_GOOD;
+
+ /* Check if the not trusted certificate has a CRL file. If there is no CRL file available for the corresponding
+ * parent certificate then return status code UA_STATUSCODE_BADCERTIFICATEISSUERREVOCATIONUNKNOWN. Refer the test
+ * case CTT/Security/Security Certificate Validation/002.js */
+ if (X509_STORE_CTX_get_check_issued (storeCtx) (storeCtx,certificateX509, certificateX509) != 1) {
+ /* Free X509_STORE_CTX and reuse it for certification verification */
+ if (storeCtx != NULL) {
+ X509_STORE_CTX_free(storeCtx);
+ }
+
+ /* Initialised X509_STORE_CTX sructure*/
+ storeCtx = X509_STORE_CTX_new();
+
+ /* Sets up X509_STORE_CTX structure for a subsequent verification operation */
+ X509_STORE_set_flags(store, 0);
+ X509_STORE_CTX_init (storeCtx, store, certificateX509,ctx->skIssue);
+
+ /* Set trust list to ctx */
+ (void) X509_STORE_CTX_trusted_stack (storeCtx, ctx->skTrusted);
+
+ /* Set crls to ctx */
+ X509_STORE_CTX_set0_crls (storeCtx, ctx->skCrls);
+
+ /* Set flags for CRL check */
+ X509_STORE_CTX_set_flags (storeCtx, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
+
+ opensslRet = X509_verify_cert (storeCtx);
+ if (opensslRet != 1) {
+ opensslRet = X509_STORE_CTX_get_error (storeCtx);
+ if (opensslRet == X509_V_ERR_UNABLE_TO_GET_CRL) {
+ ret = UA_STATUSCODE_BADCERTIFICATEISSUERREVOCATIONUNKNOWN;
+ }
+ }
+ }
+ }
+ else {
+ opensslRet = X509_STORE_CTX_get_error (storeCtx);
+
+ /* Check the issued certificate of a CA that is not trusted but available */
+ if(opensslRet == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN){
+ int trusted_cert_len = sk_X509_num(ctx->skTrusted);
+ int cmpVal;
+ X509 *trusted_cert;
+ const ASN1_OCTET_STRING *trusted_cert_keyid;
+ const ASN1_OCTET_STRING *remote_cert_keyid;
+
+ for (int i = 0; i < trusted_cert_len; i++) {
+ trusted_cert = sk_X509_value(ctx->skTrusted, i);
+
+ /* Fetch the Subject key identifier of the certificate in trust list */
+ trusted_cert_keyid = X509_get0_subject_key_id(trusted_cert);
+
+ /* Fetch the Subject key identifier of the remote certificate */
+ remote_cert_keyid = X509_get0_subject_key_id(certificateX509);
+
+ /* Check remote certificate is present in the trust list */
+ cmpVal = ASN1_OCTET_STRING_cmp(trusted_cert_keyid, remote_cert_keyid);
+ if (cmpVal == 0){
+ ret = UA_STATUSCODE_GOOD;
+ goto cleanup;
+ }
+ }
+ }
+
+ /* Return expected OPCUA error code */
+ ret = UA_X509_Store_CTX_Error_To_UAError (opensslRet);
+ }
+cleanup:
+ if (store != NULL) {
+ X509_STORE_free (store);
+ }
+ if (storeCtx != NULL) {
+ X509_STORE_CTX_free (storeCtx);
+ }
+ if (certificateX509 != NULL) {
+ X509_free (certificateX509);
+ }
+ return ret;
+}
+
+static UA_StatusCode
+UA_VerifyCertificateAllowAll (void * verificationContext,
+ const UA_ByteString * certificate) {
+ (void) verificationContext;
+ (void) certificate;
return UA_STATUSCODE_GOOD;
}
-int UA_mbedTLS_LoadPrivateKey(const UA_ByteString *key, mbedtls_pk_context *target)
-{
- UA_ByteString data = UA_mbedTLS_CopyDataFormatAware(key);
- int mbedErr = mbedtls_pk_parse_key(target, data.data, data.length, NULL, 0);
- UA_ByteString_clear(&data);
+static UA_StatusCode
+UA_CertificateVerification_VerifyApplicationURI (void * verificationContext,
+ const UA_ByteString * certificate,
+ const UA_String * applicationURI) {
+ (void) verificationContext;
- return mbedErr;
+ const unsigned char * pData;
+ X509 * certificateX509;
+ UA_String subjectURI;
+ GENERAL_NAMES * pNames;
+ int i;
+ UA_StatusCode ret;
+
+ pData = certificate->data;
+ if (pData == NULL) {
+ return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
+ }
+
+ certificateX509 = UA_OpenSSL_LoadCertificate(certificate);
+ if (certificateX509 == NULL) {
+ return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
+ }
+
+ pNames = (GENERAL_NAMES *) X509_get_ext_d2i(certificateX509, NID_subject_alt_name,
+ NULL, NULL);
+ if (pNames == NULL) {
+ X509_free (certificateX509);
+ return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
+ }
+ for (i = 0; i < sk_GENERAL_NAME_num (pNames); i++) {
+ GENERAL_NAME * value = sk_GENERAL_NAME_value (pNames, i);
+ if (value->type == GEN_URI) {
+ subjectURI.length = (size_t) (value->d.ia5->length);
+ subjectURI.data = (UA_Byte *) UA_malloc (subjectURI.length);
+ if (subjectURI.data == NULL) {
+ X509_free (certificateX509);
+ sk_GENERAL_NAME_pop_free(pNames, GENERAL_NAME_free);
+ return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
+ }
+ (void) memcpy (subjectURI.data, value->d.ia5->data, subjectURI.length);
+ break;
+ }
+
+ }
+
+ ret = UA_STATUSCODE_GOOD;
+ if (UA_Bstrstr (subjectURI.data, subjectURI.length,
+ applicationURI->data, applicationURI->length) == NULL) {
+ ret = UA_STATUSCODE_BADCERTIFICATEURIINVALID;
+ }
+
+ X509_free (certificateX509);
+ sk_GENERAL_NAME_pop_free(pNames, GENERAL_NAME_free);
+ UA_String_clear (&subjectURI);
+ return ret;
}
-UA_StatusCode UA_mbedTLS_LoadLocalCertificate(const UA_ByteString *certData, UA_ByteString *target)
-{
- UA_ByteString data = UA_mbedTLS_CopyDataFormatAware(certData);
+/* main entry */
- mbedtls_x509_crt cert;
- mbedtls_x509_crt_init(&cert);
+UA_StatusCode
+UA_CertificateVerification_Trustlist(UA_CertificateVerification * cv,
+ const UA_ByteString * certificateTrustList,
+ size_t certificateTrustListSize,
+ const UA_ByteString * certificateIssuerList,
+ size_t certificateIssuerListSize,
+ const UA_ByteString * certificateRevocationList,
+ size_t certificateRevocationListSize) {
+ UA_StatusCode ret;
- int mbedErr = mbedtls_x509_crt_parse(&cert, data.data, data.length);
+ if (cv == NULL) {
+ return UA_STATUSCODE_BADINTERNALERROR;
+ }
- UA_StatusCode result = UA_STATUSCODE_BADINVALIDARGUMENT;
+ CertContext * context = (CertContext *) UA_malloc (sizeof (CertContext));
+ if (context == NULL) {
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ }
+ ret = UA_CertContext_Init (context);
+ if (ret != UA_STATUSCODE_GOOD) {
+ return ret;
+ }
- if (!mbedErr) {
- UA_ByteString tmp;
- tmp.data = cert.raw.p;
- tmp.length = cert.raw.len;
+ cv->verifyApplicationURI = UA_CertificateVerification_VerifyApplicationURI;
+ cv->clear = UA_CertificateVerification_clear;
+ cv->context = context;
+ if (certificateTrustListSize > 0)
+ cv->verifyCertificate = UA_CertificateVerification_Verify;
+ else
+ cv->verifyCertificate = UA_VerifyCertificateAllowAll;
+
+ if (certificateTrustListSize > 0) {
+ if (UA_skTrusted_Cert2X509 (certificateTrustList, certificateTrustListSize,
+ context) != UA_STATUSCODE_GOOD) {
+ ret = UA_STATUSCODE_BADINTERNALERROR;
+ goto errout;
+ }
+ }
- result = UA_ByteString_copy(&tmp, target);
+ if (certificateIssuerListSize > 0) {
+ if (UA_skIssuer_Cert2X509 (certificateIssuerList, certificateIssuerListSize,
+ context) != UA_STATUSCODE_GOOD) {
+ ret = UA_STATUSCODE_BADINTERNALERROR;
+ goto errout;
+ }
}
- UA_ByteString_clear(&data);
- mbedtls_x509_crt_free(&cert);
- return result;
+ if (certificateRevocationListSize > 0) {
+ if (UA_skCrls_Cert2X509 (certificateRevocationList, certificateRevocationListSize,
+ context) != UA_STATUSCODE_GOOD) {
+ ret = UA_STATUSCODE_BADINTERNALERROR;
+ goto errout;
+ }
+ }
+
+ return UA_STATUSCODE_GOOD;
+
+errout:
+ UA_CertificateVerification_clear (cv);
+ return ret;
}
-// mbedTLS expects PEM data to be null terminated
-// The data length parameter must include the null terminator
-UA_ByteString UA_mbedTLS_CopyDataFormatAware(const UA_ByteString *data)
-{
- UA_ByteString result;
- UA_ByteString_init(&result);
+#ifdef __linux__ /* Linux only so far */
+UA_StatusCode
+UA_CertificateVerification_CertFolders(UA_CertificateVerification * cv,
+ const char * trustListFolder,
+ const char * issuerListFolder,
+ const char * revocationListFolder) {
+ UA_StatusCode ret;
+ if (cv == NULL) {
+ return UA_STATUSCODE_BADINTERNALERROR;
+ }
- if (!data->length)
- return result;
+ CertContext * context = (CertContext *) UA_malloc (sizeof (CertContext));
+ if (context == NULL) {
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ }
+ ret = UA_CertContext_Init (context);
+ if (ret != UA_STATUSCODE_GOOD) {
+ return ret;
+ }
- if (data->length && data->data[0] == '-') {
- UA_ByteString_allocBuffer(&result, data->length + 1);
- memcpy(result.data, data->data, data->length);
- result.data[data->length] = '\0';
+ cv->verifyApplicationURI = UA_CertificateVerification_VerifyApplicationURI;
+ cv->clear = UA_CertificateVerification_clear;
+ cv->context = context;
+ if(trustListFolder == NULL &&
+ issuerListFolder == NULL &&
+ revocationListFolder == NULL) {
+ cv->verifyCertificate = UA_VerifyCertificateAllowAll;
} else {
- UA_ByteString_copy(data, &result);
+ cv->verifyCertificate = UA_CertificateVerification_Verify;
}
- return result;
+ /* Only set the folder paths. They will be reloaded during runtime. */
+
+ context->trustListFolder = UA_STRING_ALLOC(trustListFolder);
+ context->issuerListFolder = UA_STRING_ALLOC(issuerListFolder);
+ context->revocationListFolder = UA_STRING_ALLOC(revocationListFolder);
+
+ return UA_STATUSCODE_GOOD;
}
+#endif
+
+#endif /* end of defined(UA_ENABLE_ENCRYPTION_OPENSSL) || defined(UA_ENABLE_ENCRYPTION_LIBRESSL) */
+
+/**** amalgamated original file "/plugins/crypto/mbedtls/securitypolicy_mbedtls_common.h" ****/
+
+/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
+ * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
+ *
+ * Copyright 2019 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
+ */
+
+
+
+#if defined(UA_ENABLE_ENCRYPTION_MBEDTLS) || defined(UA_ENABLE_PUBSUB_ENCRYPTION)
+
+#include <mbedtls/md.h>
+#include <mbedtls/x509_crt.h>
+#include <mbedtls/ctr_drbg.h>
+
+// MBEDTLS_ENTROPY_HARDWARE_ALT should be defined if your hardware does not supportd platform entropy
+
+#define UA_SHA1_LENGTH 20
+
+_UA_BEGIN_DECLS
+
+void
+swapBuffers(UA_ByteString *const bufA, UA_ByteString *const bufB);
+
+void
+mbedtls_hmac(mbedtls_md_context_t *context, const UA_ByteString *key,
+ const UA_ByteString *in, unsigned char *out);
+
+UA_StatusCode
+mbedtls_generateKey(mbedtls_md_context_t *context,
+ const UA_ByteString *secret, const UA_ByteString *seed,
+ UA_ByteString *out);
+
+UA_StatusCode
+mbedtls_verifySig_sha1(mbedtls_x509_crt *certificate, const UA_ByteString *message,
+ const UA_ByteString *signature);
+
+UA_StatusCode
+mbedtls_sign_sha1(mbedtls_pk_context *localPrivateKey,
+ mbedtls_ctr_drbg_context *drbgContext,
+ const UA_ByteString *message,
+ UA_ByteString *signature);
+
+UA_StatusCode
+mbedtls_thumbprint_sha1(const UA_ByteString *certificate,
+ UA_ByteString *thumbprint);
+
+/* Set the hashing scheme before calling
+ * E.g. mbedtls_rsa_set_padding(context, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA1); */
+UA_StatusCode
+mbedtls_encrypt_rsaOaep(mbedtls_rsa_context *context,
+ mbedtls_ctr_drbg_context *drbgContext,
+ UA_ByteString *data, const size_t plainTextBlockSize);
+
+UA_StatusCode
+mbedtls_decrypt_rsaOaep(mbedtls_pk_context *localPrivateKey,
+ mbedtls_ctr_drbg_context *drbgContext,
+ UA_ByteString *data);
+
+int UA_mbedTLS_LoadPrivateKey(const UA_ByteString *key, mbedtls_pk_context *target, void *p_rng);
+
+UA_StatusCode UA_mbedTLS_LoadLocalCertificate(const UA_ByteString *certData, UA_ByteString *target);
+
+UA_ByteString UA_mbedTLS_CopyDataFormatAware(const UA_ByteString *data);
+
+_UA_END_DECLS
#endif
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/plugins/securityPolicies/ua_securitypolicy_basic128rsa15.c" ***********************************/
+
+/**** amalgamated original file "/plugins/crypto/mbedtls/ua_securitypolicy_basic128rsa15.c" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -58795,7 +66827,6 @@ UA_ByteString UA_mbedTLS_CopyDataFormatAware(const UA_ByteString *data)
#include <mbedtls/aes.h>
#include <mbedtls/ctr_drbg.h>
#include <mbedtls/entropy.h>
-#include <mbedtls/entropy_poll.h>
#include <mbedtls/error.h>
#include <mbedtls/md.h>
#include <mbedtls/sha1.h>
@@ -58844,22 +66875,20 @@ typedef struct {
/********************/
static UA_StatusCode
-asym_verify_sp_basic128rsa15(const UA_SecurityPolicy *securityPolicy,
- Basic128Rsa15_ChannelContext *cc,
+asym_verify_sp_basic128rsa15(Basic128Rsa15_ChannelContext *cc,
const UA_ByteString *message,
const UA_ByteString *signature) {
- if(securityPolicy == NULL || message == NULL || signature == NULL || cc == NULL)
+ if(message == NULL || signature == NULL || cc == NULL)
return UA_STATUSCODE_BADINTERNALERROR;
return mbedtls_verifySig_sha1(&cc->remoteCertificate, message, signature);
}
static UA_StatusCode
-asym_sign_sp_basic128rsa15(const UA_SecurityPolicy *securityPolicy,
- Basic128Rsa15_ChannelContext *cc,
+asym_sign_sp_basic128rsa15(Basic128Rsa15_ChannelContext *cc,
const UA_ByteString *message,
UA_ByteString *signature) {
- if(securityPolicy == NULL || message == NULL || signature == NULL || cc == NULL)
+ if(message == NULL || signature == NULL || cc == NULL)
return UA_STATUSCODE_BADINTERNALERROR;
Basic128Rsa15_PolicyContext *pc = cc->policyContext;
@@ -58868,43 +66897,58 @@ asym_sign_sp_basic128rsa15(const UA_SecurityPolicy *securityPolicy,
}
static size_t
-asym_getLocalSignatureSize_sp_basic128rsa15(const UA_SecurityPolicy *securityPolicy,
- const Basic128Rsa15_ChannelContext *cc) {
- if(securityPolicy == NULL || cc == NULL)
+asym_getLocalSignatureSize_sp_basic128rsa15(const Basic128Rsa15_ChannelContext *cc) {
+ if(cc == NULL)
return 0;
-
+#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
return mbedtls_pk_rsa(cc->policyContext->localPrivateKey)->len;
+#else
+ return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->policyContext->localPrivateKey));
+#endif
+
+
}
static size_t
-asym_getRemoteSignatureSize_sp_basic128rsa15(const UA_SecurityPolicy *securityPolicy,
- const Basic128Rsa15_ChannelContext *cc) {
- if(securityPolicy == NULL || cc == NULL)
+asym_getRemoteSignatureSize_sp_basic128rsa15(const Basic128Rsa15_ChannelContext *cc) {
+ if(cc == NULL)
return 0;
+#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
return mbedtls_pk_rsa(cc->remoteCertificate.pk)->len;
+#else
+ return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->remoteCertificate.pk));
+#endif
+
}
static UA_StatusCode
-asym_encrypt_sp_basic128rsa15(const UA_SecurityPolicy *securityPolicy,
- Basic128Rsa15_ChannelContext *cc,
+asym_encrypt_sp_basic128rsa15(Basic128Rsa15_ChannelContext *cc,
UA_ByteString *data) {
- if(securityPolicy == NULL || cc == NULL || data == NULL)
+ if(cc == NULL || data == NULL)
return UA_STATUSCODE_BADINTERNALERROR;
- const size_t plainTextBlockSize = securityPolicy->asymmetricModule.cryptoModule.encryptionAlgorithm.
- getRemotePlainTextBlockSize(securityPolicy, cc);
+ mbedtls_rsa_context *remoteRsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk);
+ mbedtls_rsa_set_padding(remoteRsaContext, MBEDTLS_RSA_PKCS_V15, MBEDTLS_MD_NONE);
+
+#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
+ size_t plainTextBlockSize = remoteRsaContext->len - UA_SECURITYPOLICY_BASIC128RSA15_RSAPADDING_LEN;
+#else
+ size_t keylen = mbedtls_rsa_get_len(remoteRsaContext);
+ size_t plainTextBlockSize = mbedtls_rsa_get_len(remoteRsaContext) -
+ UA_SECURITYPOLICY_BASIC128RSA15_RSAPADDING_LEN;
+#endif
if(data->length % plainTextBlockSize != 0)
return UA_STATUSCODE_BADINTERNALERROR;
- mbedtls_rsa_context *remoteRsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk);
- mbedtls_rsa_set_padding(remoteRsaContext, MBEDTLS_RSA_PKCS_V15, 0);
-
+ size_t blocks = data->length / plainTextBlockSize;
UA_ByteString encrypted;
- const size_t bufferOverhead =
- UA_SecurityPolicy_getRemoteAsymEncryptionBufferLengthOverhead(securityPolicy, cc, data->length);
- UA_StatusCode retval = UA_ByteString_allocBuffer(&encrypted, data->length + bufferOverhead);
+#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
+ UA_StatusCode retval = UA_ByteString_allocBuffer(&encrypted, blocks * remoteRsaContext->len);
+#else
+ UA_StatusCode retval = UA_ByteString_allocBuffer(&encrypted, blocks * keylen);
+#endif
if(retval != UA_STATUSCODE_GOOD)
return retval;
@@ -58921,7 +66965,7 @@ asym_encrypt_sp_basic128rsa15(const UA_SecurityPolicy *securityPolicy,
mbedtls_ctr_drbg_random,
&pc->drbgContext);
if(mbedErr) {
- UA_ByteString_deleteMembers(&encrypted);
+ UA_ByteString_clear(&encrypted);
return UA_STATUSCODE_BADINTERNALERROR;
}
@@ -58931,23 +66975,27 @@ asym_encrypt_sp_basic128rsa15(const UA_SecurityPolicy *securityPolicy,
}
memcpy(data->data, encrypted.data, offset);
- UA_ByteString_deleteMembers(&encrypted);
+ UA_ByteString_clear(&encrypted);
return UA_STATUSCODE_GOOD;
}
static UA_StatusCode
-asym_decrypt_sp_basic128rsa15(const UA_SecurityPolicy *securityPolicy,
- Basic128Rsa15_ChannelContext *cc,
+asym_decrypt_sp_basic128rsa15(Basic128Rsa15_ChannelContext *cc,
UA_ByteString *data) {
- if(securityPolicy == NULL || cc == NULL || data == NULL)
+ if(cc == NULL || data == NULL)
return UA_STATUSCODE_BADINTERNALERROR;
mbedtls_rsa_context *rsaContext = mbedtls_pk_rsa(cc->policyContext->localPrivateKey);
- mbedtls_rsa_set_padding(rsaContext, MBEDTLS_RSA_PKCS_V15, 0);
-
+ mbedtls_rsa_set_padding(rsaContext, MBEDTLS_RSA_PKCS_V15, MBEDTLS_MD_NONE);
+#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
if(data->length % rsaContext->len != 0)
+ return UA_STATUSCODE_BADINTERNALERROR;
+#else
+ size_t keylen = mbedtls_rsa_get_len(rsaContext);
+ if(data->length % keylen != 0)
return UA_STATUSCODE_BADINTERNALERROR;
+#endif
size_t inOffset = 0;
size_t outOffset = 0;
@@ -58955,14 +67003,25 @@ asym_decrypt_sp_basic128rsa15(const UA_SecurityPolicy *securityPolicy,
unsigned char buf[512];
while(inOffset < data->length) {
+#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
int mbedErr = mbedtls_pk_decrypt(&cc->policyContext->localPrivateKey,
data->data + inOffset, rsaContext->len,
buf, &outLength, 512, NULL, NULL);
+#else
+ int mbedErr = mbedtls_pk_decrypt(&cc->policyContext->localPrivateKey,
+ data->data + inOffset, keylen,
+ buf, &outLength, 512, NULL, NULL);
+#endif
+
if(mbedErr)
return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
memcpy(data->data + outOffset, buf, outLength);
+#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
inOffset += rsaContext->len;
+#else
+ inOffset += keylen;
+#endif
outOffset += outLength;
}
@@ -58971,29 +67030,45 @@ asym_decrypt_sp_basic128rsa15(const UA_SecurityPolicy *securityPolicy,
}
static size_t
-asym_getLocalEncryptionKeyLength_sp_basic128rsa15(const UA_SecurityPolicy *securityPolicy,
- const Basic128Rsa15_ChannelContext *cc) {
- return mbedtls_pk_get_len(&cc->policyContext->localPrivateKey) * 8;
+asym_getLocalEncryptionKeyLength_sp_basic128rsa15(const Basic128Rsa15_ChannelContext *cc) {
+#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
+ mbedtls_rsa_context *const rsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk);
+ return rsaContext->len;
+#else
+ if(cc == NULL)
+ return 0;
+ return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->remoteCertificate.pk));
+#endif
}
static size_t
-asym_getRemoteEncryptionKeyLength_sp_basic128rsa15(const UA_SecurityPolicy *securityPolicy,
- const Basic128Rsa15_ChannelContext *cc) {
+asym_getRemoteEncryptionKeyLength_sp_basic128rsa15(const Basic128Rsa15_ChannelContext *cc) {
return mbedtls_pk_get_len(&cc->remoteCertificate.pk) * 8;
}
static size_t
-asym_getRemoteBlockSize_sp_basic128rsa15(const UA_SecurityPolicy *securityPolicy,
- const Basic128Rsa15_ChannelContext *cc) {
+asym_getRemoteBlockSize_sp_basic128rsa15(const Basic128Rsa15_ChannelContext *cc) {
+#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
mbedtls_rsa_context *const rsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk);
return rsaContext->len;
+#else
+ if(cc == NULL)
+ return 0;
+ return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->remoteCertificate.pk));
+#endif
}
static size_t
-asym_getRemotePlainTextBlockSize_sp_basic128rsa15(const UA_SecurityPolicy *securityPolicy,
- const Basic128Rsa15_ChannelContext *cc) {
+asym_getRemotePlainTextBlockSize_sp_basic128rsa15(const Basic128Rsa15_ChannelContext *cc) {
+#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
mbedtls_rsa_context *const rsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk);
return rsaContext->len - UA_SECURITYPOLICY_BASIC128RSA15_RSAPADDING_LEN;
+#else
+ if(cc == NULL)
+ return 0;
+ return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->remoteCertificate.pk)) -
+ UA_SECURITYPOLICY_BASIC128RSA15_RSAPADDING_LEN;
+#endif
}
static UA_StatusCode
@@ -59023,22 +67098,17 @@ asymmetricModule_compareCertificateThumbprint_sp_basic128rsa15(const UA_Security
/*******************/
static UA_StatusCode
-sym_verify_sp_basic128rsa15(const UA_SecurityPolicy *securityPolicy,
- Basic128Rsa15_ChannelContext *cc,
+sym_verify_sp_basic128rsa15(Basic128Rsa15_ChannelContext *cc,
const UA_ByteString *message,
const UA_ByteString *signature) {
- if(securityPolicy == NULL || cc == NULL || message == NULL || signature == NULL)
+ if(cc == NULL || message == NULL || signature == NULL)
return UA_STATUSCODE_BADINTERNALERROR;
/* Compute MAC */
- if(signature->length != UA_SHA1_LENGTH) {
- UA_LOG_ERROR(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY,
- "Signature size does not have the desired size defined by the security policy");
+ if(signature->length != UA_SHA1_LENGTH)
return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
- }
- Basic128Rsa15_PolicyContext *pc =
- (Basic128Rsa15_PolicyContext *)securityPolicy->policyContext;
+ Basic128Rsa15_PolicyContext *pc = cc->policyContext;
unsigned char mac[UA_SHA1_LENGTH];
mbedtls_hmac(&pc->sha1MdContext, &cc->remoteSymSigningKey, message, mac);
@@ -59050,8 +67120,7 @@ sym_verify_sp_basic128rsa15(const UA_SecurityPolicy *securityPolicy,
}
static UA_StatusCode
-sym_sign_sp_basic128rsa15(const UA_SecurityPolicy *securityPolicy,
- const Basic128Rsa15_ChannelContext *cc,
+sym_sign_sp_basic128rsa15(const Basic128Rsa15_ChannelContext *cc,
const UA_ByteString *message,
UA_ByteString *signature) {
if(signature->length != UA_SHA1_LENGTH)
@@ -59063,55 +67132,42 @@ sym_sign_sp_basic128rsa15(const UA_SecurityPolicy *securityPolicy,
}
static size_t
-sym_getSignatureSize_sp_basic128rsa15(const UA_SecurityPolicy *securityPolicy,
- const void *channelContext) {
+sym_getSignatureSize_sp_basic128rsa15(const void *channelContext) {
return UA_SHA1_LENGTH;
}
static size_t
-sym_getSigningKeyLength_sp_basic128rsa15(const UA_SecurityPolicy *const securityPolicy,
- const void *const channelContext) {
+sym_getSigningKeyLength_sp_basic128rsa15(const void *const channelContext) {
return UA_BASIC128RSA15_SYM_SIGNING_KEY_LENGTH;
}
static size_t
-sym_getEncryptionKeyLength_sp_basic128rsa15(const UA_SecurityPolicy *securityPolicy,
- const void *channelContext) {
+sym_getEncryptionKeyLength_sp_basic128rsa15(const void *channelContext) {
return UA_SECURITYPOLICY_BASIC128RSA15_SYM_KEY_LENGTH;
}
static size_t
-sym_getEncryptionBlockSize_sp_basic128rsa15(const UA_SecurityPolicy *const securityPolicy,
- const void *const channelContext) {
+sym_getEncryptionBlockSize_sp_basic128rsa15(const void *const channelContext) {
return UA_SECURITYPOLICY_BASIC128RSA15_SYM_ENCRYPTION_BLOCK_SIZE;
}
static size_t
-sym_getPlainTextBlockSize_sp_basic128rsa15(const UA_SecurityPolicy *const securityPolicy,
- const void *const channelContext) {
+sym_getPlainTextBlockSize_sp_basic128rsa15(const void *const channelContext) {
return UA_SECURITYPOLICY_BASIC128RSA15_SYM_PLAIN_TEXT_BLOCK_SIZE;
}
static UA_StatusCode
-sym_encrypt_sp_basic128rsa15(const UA_SecurityPolicy *securityPolicy,
- const Basic128Rsa15_ChannelContext *cc,
+sym_encrypt_sp_basic128rsa15(const Basic128Rsa15_ChannelContext *cc,
UA_ByteString *data) {
- if(securityPolicy == NULL || cc == NULL || data == NULL)
+ if(cc == NULL || data == NULL)
return UA_STATUSCODE_BADINTERNALERROR;
- if(cc->localSymIv.length !=
- securityPolicy->symmetricModule.cryptoModule.encryptionAlgorithm.getLocalBlockSize(securityPolicy, cc))
+ if(cc->localSymIv.length != UA_SECURITYPOLICY_BASIC128RSA15_SYM_ENCRYPTION_BLOCK_SIZE)
return UA_STATUSCODE_BADINTERNALERROR;
- size_t plainTextBlockSize =
- securityPolicy->symmetricModule.cryptoModule.encryptionAlgorithm.getLocalPlainTextBlockSize(securityPolicy, cc);
-
- if(data->length % plainTextBlockSize != 0) {
- UA_LOG_ERROR(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY,
- "Length of data to encrypt is not a multiple of the plain text block size."
- "Padding might not have been calculated appropriately.");
+ size_t plainTextBlockSize = UA_SECURITYPOLICY_BASIC128RSA15_SYM_PLAIN_TEXT_BLOCK_SIZE;
+ if(data->length % plainTextBlockSize != 0)
return UA_STATUSCODE_BADINTERNALERROR;
- }
/* Keylength in bits */
unsigned int keylength = (unsigned int)(cc->localSymEncryptingKey.length * 8);
@@ -59129,32 +67185,27 @@ sym_encrypt_sp_basic128rsa15(const UA_SecurityPolicy *securityPolicy,
ivCopy.data, data->data, data->data);
if(mbedErr)
retval = UA_STATUSCODE_BADINTERNALERROR;
- UA_ByteString_deleteMembers(&ivCopy);
+ UA_ByteString_clear(&ivCopy);
return retval;
}
static UA_StatusCode
-sym_decrypt_sp_basic128rsa15(const UA_SecurityPolicy *securityPolicy,
- const Basic128Rsa15_ChannelContext *cc,
+sym_decrypt_sp_basic128rsa15(const Basic128Rsa15_ChannelContext *cc,
UA_ByteString *data) {
- if(securityPolicy == NULL || cc == NULL || data == NULL)
+ if(cc == NULL || data == NULL)
return UA_STATUSCODE_BADINTERNALERROR;
- size_t encryptionBlockSize = securityPolicy->symmetricModule.cryptoModule.
- encryptionAlgorithm.getRemoteBlockSize(securityPolicy, cc);
-
+ size_t encryptionBlockSize = UA_SECURITYPOLICY_BASIC128RSA15_SYM_ENCRYPTION_BLOCK_SIZE;
if(cc->remoteSymIv.length != encryptionBlockSize)
return UA_STATUSCODE_BADINTERNALERROR;
- if(data->length % encryptionBlockSize != 0) {
- UA_LOG_ERROR(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY,
- "Length of data to decrypt is not a multiple of the encryptingBlock size.");
+ if(data->length % encryptionBlockSize != 0)
return UA_STATUSCODE_BADINTERNALERROR;
- }
unsigned int keylength = (unsigned int)(cc->remoteSymEncryptingKey.length * 8);
mbedtls_aes_context aesContext;
- int mbedErr = mbedtls_aes_setkey_dec(&aesContext, cc->remoteSymEncryptingKey.data, keylength);
+ int mbedErr = mbedtls_aes_setkey_dec(&aesContext,
+ cc->remoteSymEncryptingKey.data, keylength);
if(mbedErr)
return UA_STATUSCODE_BADINTERNALERROR;
@@ -59167,36 +67218,27 @@ sym_decrypt_sp_basic128rsa15(const UA_SecurityPolicy *securityPolicy,
ivCopy.data, data->data, data->data);
if(mbedErr)
retval = UA_STATUSCODE_BADINTERNALERROR;
- UA_ByteString_deleteMembers(&ivCopy);
+ UA_ByteString_clear(&ivCopy);
return retval;
}
static UA_StatusCode
-sym_generateKey_sp_basic128rsa15(const UA_SecurityPolicy *securityPolicy,
- const UA_ByteString *secret, const UA_ByteString *seed,
- UA_ByteString *out) {
- if(securityPolicy == NULL || secret == NULL || seed == NULL || out == NULL)
+sym_generateKey_sp_basic128rsa15(void *policyContext, const UA_ByteString *secret,
+ const UA_ByteString *seed, UA_ByteString *out) {
+ if(secret == NULL || seed == NULL || out == NULL)
return UA_STATUSCODE_BADINTERNALERROR;
-
- Basic128Rsa15_PolicyContext *pc =
- (Basic128Rsa15_PolicyContext *)securityPolicy->policyContext;
-
+ Basic128Rsa15_PolicyContext *pc = (Basic128Rsa15_PolicyContext *)policyContext;
return mbedtls_generateKey(&pc->sha1MdContext, secret, seed, out);
}
static UA_StatusCode
-sym_generateNonce_sp_basic128rsa15(const UA_SecurityPolicy *securityPolicy,
- UA_ByteString *out) {
- if(securityPolicy == NULL || securityPolicy->policyContext == NULL || out == NULL)
+sym_generateNonce_sp_basic128rsa15(void *policyContext, UA_ByteString *out) {
+ if(out == NULL)
return UA_STATUSCODE_BADINTERNALERROR;
-
- Basic128Rsa15_PolicyContext *pc =
- (Basic128Rsa15_PolicyContext *)securityPolicy->policyContext;
-
+ Basic128Rsa15_PolicyContext *pc = (Basic128Rsa15_PolicyContext *)policyContext;
int mbedErr = mbedtls_ctr_drbg_random(&pc->drbgContext, out->data, out->length);
if(mbedErr)
return UA_STATUSCODE_BADUNEXPECTEDERROR;
-
return UA_STATUSCODE_GOOD;
}
@@ -59218,26 +67260,29 @@ parseRemoteCertificate_sp_basic128rsa15(Basic128Rsa15_ChannelContext *cc,
return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
/* Check the key length */
+#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
mbedtls_rsa_context *rsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk);
if(rsaContext->len < UA_SECURITYPOLICY_BASIC128RSA15_MINASYMKEYLENGTH ||
rsaContext->len > UA_SECURITYPOLICY_BASIC128RSA15_MAXASYMKEYLENGTH)
return UA_STATUSCODE_BADCERTIFICATEUSENOTALLOWED;
-
+#else
+ size_t keylen = mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->remoteCertificate.pk));
+ if(keylen < UA_SECURITYPOLICY_BASIC128RSA15_MINASYMKEYLENGTH ||
+ keylen > UA_SECURITYPOLICY_BASIC128RSA15_MAXASYMKEYLENGTH)
+ return UA_STATUSCODE_BADCERTIFICATEUSENOTALLOWED;
+#endif
return UA_STATUSCODE_GOOD;
}
static void
channelContext_deleteContext_sp_basic128rsa15(Basic128Rsa15_ChannelContext *cc) {
- UA_ByteString_deleteMembers(&cc->localSymSigningKey);
- UA_ByteString_deleteMembers(&cc->localSymEncryptingKey);
- UA_ByteString_deleteMembers(&cc->localSymIv);
-
- UA_ByteString_deleteMembers(&cc->remoteSymSigningKey);
- UA_ByteString_deleteMembers(&cc->remoteSymEncryptingKey);
- UA_ByteString_deleteMembers(&cc->remoteSymIv);
-
+ UA_ByteString_clear(&cc->localSymSigningKey);
+ UA_ByteString_clear(&cc->localSymEncryptingKey);
+ UA_ByteString_clear(&cc->localSymIv);
+ UA_ByteString_clear(&cc->remoteSymSigningKey);
+ UA_ByteString_clear(&cc->remoteSymEncryptingKey);
+ UA_ByteString_clear(&cc->remoteSymIv);
mbedtls_x509_crt_free(&cc->remoteCertificate);
-
UA_free(cc);
}
@@ -59283,7 +67328,7 @@ channelContext_setLocalSymEncryptingKey_sp_basic128rsa15(Basic128Rsa15_ChannelCo
if(key == NULL || cc == NULL)
return UA_STATUSCODE_BADINTERNALERROR;
- UA_ByteString_deleteMembers(&cc->localSymEncryptingKey);
+ UA_ByteString_clear(&cc->localSymEncryptingKey);
return UA_ByteString_copy(key, &cc->localSymEncryptingKey);
}
@@ -59293,7 +67338,7 @@ channelContext_setLocalSymSigningKey_sp_basic128rsa15(Basic128Rsa15_ChannelConte
if(key == NULL || cc == NULL)
return UA_STATUSCODE_BADINTERNALERROR;
- UA_ByteString_deleteMembers(&cc->localSymSigningKey);
+ UA_ByteString_clear(&cc->localSymSigningKey);
return UA_ByteString_copy(key, &cc->localSymSigningKey);
}
@@ -59304,7 +67349,7 @@ channelContext_setLocalSymIv_sp_basic128rsa15(Basic128Rsa15_ChannelContext *cc,
if(iv == NULL || cc == NULL)
return UA_STATUSCODE_BADINTERNALERROR;
- UA_ByteString_deleteMembers(&cc->localSymIv);
+ UA_ByteString_clear(&cc->localSymIv);
return UA_ByteString_copy(iv, &cc->localSymIv);
}
@@ -59314,7 +67359,7 @@ channelContext_setRemoteSymEncryptingKey_sp_basic128rsa15(Basic128Rsa15_ChannelC
if(key == NULL || cc == NULL)
return UA_STATUSCODE_BADINTERNALERROR;
- UA_ByteString_deleteMembers(&cc->remoteSymEncryptingKey);
+ UA_ByteString_clear(&cc->remoteSymEncryptingKey);
return UA_ByteString_copy(key, &cc->remoteSymEncryptingKey);
}
@@ -59324,7 +67369,7 @@ channelContext_setRemoteSymSigningKey_sp_basic128rsa15(Basic128Rsa15_ChannelCont
if(key == NULL || cc == NULL)
return UA_STATUSCODE_BADINTERNALERROR;
- UA_ByteString_deleteMembers(&cc->remoteSymSigningKey);
+ UA_ByteString_clear(&cc->remoteSymSigningKey);
return UA_ByteString_copy(key, &cc->remoteSymSigningKey);
}
@@ -59334,7 +67379,7 @@ channelContext_setRemoteSymIv_sp_basic128rsa15(Basic128Rsa15_ChannelContext *cc,
if(iv == NULL || cc == NULL)
return UA_STATUSCODE_BADINTERNALERROR;
- UA_ByteString_deleteMembers(&cc->remoteSymIv);
+ UA_ByteString_clear(&cc->remoteSymIv);
return UA_ByteString_copy(iv, &cc->remoteSymIv);
}
@@ -59364,7 +67409,7 @@ clear_sp_basic128rsa15(UA_SecurityPolicy *securityPolicy) {
if(securityPolicy == NULL)
return;
- UA_ByteString_deleteMembers(&securityPolicy->localCertificate);
+ UA_ByteString_clear(&securityPolicy->localCertificate);
if(securityPolicy->policyContext == NULL)
return;
@@ -59377,7 +67422,7 @@ clear_sp_basic128rsa15(UA_SecurityPolicy *securityPolicy) {
mbedtls_entropy_free(&pc->entropyContext);
mbedtls_pk_free(&pc->localPrivateKey);
mbedtls_md_free(&pc->sha1MdContext);
- UA_ByteString_deleteMembers(&pc->localCertThumbprint);
+ UA_ByteString_clear(&pc->localCertThumbprint);
UA_LOG_DEBUG(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY,
"Deleted members of EndpointContext for sp_basic128rsa15");
@@ -59398,7 +67443,7 @@ updateCertificateAndPrivateKey_sp_basic128rsa15(UA_SecurityPolicy *securityPolic
Basic128Rsa15_PolicyContext *pc = (Basic128Rsa15_PolicyContext *)securityPolicy->policyContext;
- UA_ByteString_deleteMembers(&securityPolicy->localCertificate);
+ UA_ByteString_clear(&securityPolicy->localCertificate);
UA_StatusCode retval = UA_mbedTLS_LoadLocalCertificate(&newCertificate, &securityPolicy->localCertificate);
@@ -59408,7 +67453,7 @@ updateCertificateAndPrivateKey_sp_basic128rsa15(UA_SecurityPolicy *securityPolic
/* Set the new private key */
mbedtls_pk_free(&pc->localPrivateKey);
mbedtls_pk_init(&pc->localPrivateKey);
- int mbedErr = UA_mbedTLS_LoadPrivateKey(&newPrivateKey, &pc->localPrivateKey);
+ int mbedErr = UA_mbedTLS_LoadPrivateKey(&newPrivateKey, &pc->localPrivateKey, &pc->entropyContext);
if(mbedErr) {
retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
goto error;
@@ -59466,10 +67511,8 @@ policyContext_newContext_sp_basic128rsa15(UA_SecurityPolicy *securityPolicy,
goto error;
}
- /* Add the system entropy source */
- mbedErr = mbedtls_entropy_add_source(&pc->entropyContext,
- MBEDTLS_ENTROPY_POLL_METHOD, NULL, 0,
- MBEDTLS_ENTROPY_SOURCE_STRONG);
+ mbedErr = mbedtls_entropy_self_test(0);
+
if(mbedErr) {
retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
goto error;
@@ -59486,7 +67529,7 @@ policyContext_newContext_sp_basic128rsa15(UA_SecurityPolicy *securityPolicy,
}
/* Set the private key */
- mbedErr = UA_mbedTLS_LoadPrivateKey(&localPrivateKey, &pc->localPrivateKey);
+ mbedErr = UA_mbedTLS_LoadPrivateKey(&localPrivateKey, &pc->localPrivateKey, &pc->entropyContext);
if(mbedErr) {
retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
@@ -59536,15 +67579,13 @@ UA_SecurityPolicy_Basic128Rsa15(UA_SecurityPolicy *policy, const UA_ByteString l
asym_signatureAlgorithm->uri =
UA_STRING("http://www.w3.org/2000/09/xmldsig#rsa-sha1\0");
asym_signatureAlgorithm->verify =
- (UA_StatusCode (*)(const UA_SecurityPolicy *, void *,
- const UA_ByteString *, const UA_ByteString *))asym_verify_sp_basic128rsa15;
+ (UA_StatusCode (*)(void *, const UA_ByteString *, const UA_ByteString *))asym_verify_sp_basic128rsa15;
asym_signatureAlgorithm->sign =
- (UA_StatusCode (*)(const UA_SecurityPolicy *, void *,
- const UA_ByteString *, UA_ByteString *))asym_sign_sp_basic128rsa15;
+ (UA_StatusCode (*)(void *, const UA_ByteString *, UA_ByteString *))asym_sign_sp_basic128rsa15;
asym_signatureAlgorithm->getLocalSignatureSize =
- (size_t (*)(const UA_SecurityPolicy *, const void *))asym_getLocalSignatureSize_sp_basic128rsa15;
+ (size_t (*)(const void *))asym_getLocalSignatureSize_sp_basic128rsa15;
asym_signatureAlgorithm->getRemoteSignatureSize =
- (size_t (*)(const UA_SecurityPolicy *, const void *))asym_getRemoteSignatureSize_sp_basic128rsa15;
+ (size_t (*)(const void *))asym_getRemoteSignatureSize_sp_basic128rsa15;
asym_signatureAlgorithm->getLocalKeyLength = NULL; // TODO: Write function
asym_signatureAlgorithm->getRemoteKeyLength = NULL; // TODO: Write function
@@ -59552,20 +67593,17 @@ UA_SecurityPolicy_Basic128Rsa15(UA_SecurityPolicy *policy, const UA_ByteString l
&asymmetricModule->cryptoModule.encryptionAlgorithm;
asym_encryptionAlgorithm->uri = UA_STRING("http://www.w3.org/2001/04/xmlenc#rsa-1_5");
asym_encryptionAlgorithm->encrypt =
- (UA_StatusCode(*)(const UA_SecurityPolicy *, void *, UA_ByteString *))asym_encrypt_sp_basic128rsa15;
+ (UA_StatusCode(*)(void *, UA_ByteString *))asym_encrypt_sp_basic128rsa15;
asym_encryptionAlgorithm->decrypt =
- (UA_StatusCode(*)(const UA_SecurityPolicy *, void *, UA_ByteString *))
- asym_decrypt_sp_basic128rsa15;
+ (UA_StatusCode(*)(void *, UA_ByteString *)) asym_decrypt_sp_basic128rsa15;
asym_encryptionAlgorithm->getLocalKeyLength =
- (size_t (*)(const UA_SecurityPolicy *, const void *))asym_getLocalEncryptionKeyLength_sp_basic128rsa15;
+ (size_t (*)(const void *))asym_getLocalEncryptionKeyLength_sp_basic128rsa15;
asym_encryptionAlgorithm->getRemoteKeyLength =
- (size_t (*)(const UA_SecurityPolicy *, const void *))asym_getRemoteEncryptionKeyLength_sp_basic128rsa15;
- asym_encryptionAlgorithm->getLocalBlockSize = NULL; // TODO: Write function
- asym_encryptionAlgorithm->getRemoteBlockSize = (size_t (*)(const UA_SecurityPolicy *,
- const void *))asym_getRemoteBlockSize_sp_basic128rsa15;
- asym_encryptionAlgorithm->getLocalPlainTextBlockSize = NULL; // TODO: Write function
+ (size_t (*)(const void *))asym_getRemoteEncryptionKeyLength_sp_basic128rsa15;
+ asym_encryptionAlgorithm->getRemoteBlockSize =
+ (size_t (*)(const void *))asym_getRemoteBlockSize_sp_basic128rsa15;
asym_encryptionAlgorithm->getRemotePlainTextBlockSize =
- (size_t (*)(const UA_SecurityPolicy *, const void *))asym_getRemotePlainTextBlockSize_sp_basic128rsa15;
+ (size_t (*)(const void *))asym_getRemotePlainTextBlockSize_sp_basic128rsa15;
asymmetricModule->makeCertificateThumbprint = asym_makeThumbprint_sp_basic128rsa15;
asymmetricModule->compareCertificateThumbprint =
@@ -59580,37 +67618,30 @@ UA_SecurityPolicy_Basic128Rsa15(UA_SecurityPolicy *policy, const UA_ByteString l
sym_signatureAlgorithm->uri =
UA_STRING("http://www.w3.org/2000/09/xmldsig#hmac-sha1\0");
sym_signatureAlgorithm->verify =
- (UA_StatusCode (*)(const UA_SecurityPolicy *, void *, const UA_ByteString *,
+ (UA_StatusCode (*)(void *, const UA_ByteString *,
const UA_ByteString *))sym_verify_sp_basic128rsa15;
sym_signatureAlgorithm->sign =
- (UA_StatusCode (*)(const UA_SecurityPolicy *, void *,
- const UA_ByteString *, UA_ByteString *))sym_sign_sp_basic128rsa15;
+ (UA_StatusCode (*)(void *, const UA_ByteString *, UA_ByteString *))sym_sign_sp_basic128rsa15;
sym_signatureAlgorithm->getLocalSignatureSize = sym_getSignatureSize_sp_basic128rsa15;
sym_signatureAlgorithm->getRemoteSignatureSize = sym_getSignatureSize_sp_basic128rsa15;
sym_signatureAlgorithm->getLocalKeyLength =
- (size_t (*)(const UA_SecurityPolicy *,
- const void *))sym_getSigningKeyLength_sp_basic128rsa15;
+ (size_t (*)(const void *))sym_getSigningKeyLength_sp_basic128rsa15;
sym_signatureAlgorithm->getRemoteKeyLength =
- (size_t (*)(const UA_SecurityPolicy *,
- const void *))sym_getSigningKeyLength_sp_basic128rsa15;
+ (size_t (*)(const void *))sym_getSigningKeyLength_sp_basic128rsa15;
UA_SecurityPolicyEncryptionAlgorithm *sym_encryptionAlgorithm =
&symmetricModule->cryptoModule.encryptionAlgorithm;
sym_encryptionAlgorithm->uri = UA_STRING("http://www.w3.org/2001/04/xmlenc#aes128-cbc");
sym_encryptionAlgorithm->encrypt =
- (UA_StatusCode(*)(const UA_SecurityPolicy *, void *, UA_ByteString *))sym_encrypt_sp_basic128rsa15;
+ (UA_StatusCode(*)(void *, UA_ByteString *))sym_encrypt_sp_basic128rsa15;
sym_encryptionAlgorithm->decrypt =
- (UA_StatusCode(*)(const UA_SecurityPolicy *, void *, UA_ByteString *))sym_decrypt_sp_basic128rsa15;
+ (UA_StatusCode(*)(void *, UA_ByteString *))sym_decrypt_sp_basic128rsa15;
sym_encryptionAlgorithm->getLocalKeyLength = sym_getEncryptionKeyLength_sp_basic128rsa15;
sym_encryptionAlgorithm->getRemoteKeyLength = sym_getEncryptionKeyLength_sp_basic128rsa15;
- sym_encryptionAlgorithm->getLocalBlockSize =
- (size_t (*)(const UA_SecurityPolicy *, const void *))sym_getEncryptionBlockSize_sp_basic128rsa15;
sym_encryptionAlgorithm->getRemoteBlockSize =
- (size_t (*)(const UA_SecurityPolicy *, const void *))sym_getEncryptionBlockSize_sp_basic128rsa15;
- sym_encryptionAlgorithm->getLocalPlainTextBlockSize =
- (size_t (*)(const UA_SecurityPolicy *, const void *))sym_getPlainTextBlockSize_sp_basic128rsa15;
+ (size_t (*)(const void *))sym_getEncryptionBlockSize_sp_basic128rsa15;
sym_encryptionAlgorithm->getRemotePlainTextBlockSize =
- (size_t (*)(const UA_SecurityPolicy *, const void *))sym_getPlainTextBlockSize_sp_basic128rsa15;
+ (size_t (*)(const void *))sym_getPlainTextBlockSize_sp_basic128rsa15;
symmetricModule->secureChannelNonceLength = 16;
// Use the same signature algorithm as the asymmetric component for certificate signing (see standard)
@@ -59650,7 +67681,7 @@ UA_SecurityPolicy_Basic128Rsa15(UA_SecurityPolicy *policy, const UA_ByteString l
#endif
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/plugins/securityPolicies/ua_securitypolicy_basic256.c" ***********************************/
+/**** amalgamated original file "/plugins/crypto/mbedtls/ua_securitypolicy_basic256.c" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -59670,7 +67701,6 @@ UA_SecurityPolicy_Basic128Rsa15(UA_SecurityPolicy *policy, const UA_ByteString l
#include <mbedtls/aes.h>
#include <mbedtls/entropy.h>
-#include <mbedtls/entropy_poll.h>
#include <mbedtls/error.h>
#include <mbedtls/sha1.h>
#include <mbedtls/version.h>
@@ -59719,11 +67749,10 @@ typedef struct {
/* VERIFY AsymmetricSignatureAlgorithm_RSA-PKCS15-SHA2-256 */
static UA_StatusCode
-asym_verify_sp_basic256(const UA_SecurityPolicy *securityPolicy,
- Basic256_ChannelContext *cc,
+asym_verify_sp_basic256(Basic256_ChannelContext *cc,
const UA_ByteString *message,
const UA_ByteString *signature) {
- if(securityPolicy == NULL || message == NULL || signature == NULL || cc == NULL)
+ if(message == NULL || signature == NULL || cc == NULL)
return UA_STATUSCODE_BADINTERNALERROR;
return mbedtls_verifySig_sha1(&cc->remoteCertificate, message, signature);
@@ -59731,11 +67760,10 @@ asym_verify_sp_basic256(const UA_SecurityPolicy *securityPolicy,
/* AsymmetricSignatureAlgorithm_RSA-PKCS15-SHA2-256 */
static UA_StatusCode
-asym_sign_sp_basic256(const UA_SecurityPolicy *securityPolicy,
- Basic256_ChannelContext *cc,
+asym_sign_sp_basic256(Basic256_ChannelContext *cc,
const UA_ByteString *message,
UA_ByteString *signature) {
- if(securityPolicy == NULL || message == NULL || signature == NULL || cc == NULL)
+ if(message == NULL || signature == NULL || cc == NULL)
return UA_STATUSCODE_BADINTERNALERROR;
Basic256_PolicyContext *pc = cc->policyContext;
@@ -59744,31 +67772,49 @@ asym_sign_sp_basic256(const UA_SecurityPolicy *securityPolicy,
}
static size_t
-asym_getLocalSignatureSize_sp_basic256(const UA_SecurityPolicy *securityPolicy,
- const Basic256_ChannelContext *cc) {
- if(securityPolicy == NULL || cc == NULL)
+asym_getLocalSignatureSize_sp_basic256(const Basic256_ChannelContext *cc) {
+ if(cc == NULL)
return 0;
+#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
return mbedtls_pk_rsa(cc->policyContext->localPrivateKey)->len;
+#else
+ return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->policyContext->localPrivateKey));
+
+#endif
}
static size_t
-asym_getRemoteSignatureSize_sp_basic256(const UA_SecurityPolicy *securityPolicy,
- const Basic256_ChannelContext *cc) {
- if(securityPolicy == NULL || cc == NULL)
+asym_getRemoteSignatureSize_sp_basic256(const Basic256_ChannelContext *cc) {
+ if(cc == NULL)
return 0;
+#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
return mbedtls_pk_rsa(cc->remoteCertificate.pk)->len;
+#else
+ return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->remoteCertificate.pk));
+#endif
+}
+
+static size_t
+asym_getRemotePlainTextBlockSize_sp_basic256(const Basic256_ChannelContext *cc) {
+#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
+ mbedtls_rsa_context *const rsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk);
+ return rsaContext->len - UA_SECURITYPOLICY_BASIC256SHA1_RSAPADDING_LEN;
+#else
+ if(cc == NULL)
+ return 0;
+ return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->remoteCertificate.pk)) -
+ UA_SECURITYPOLICY_BASIC256SHA1_RSAPADDING_LEN;
+#endif
}
/* AsymmetricEncryptionAlgorithm_RSA-OAEP-SHA1 */
static UA_StatusCode
-asym_encrypt_sp_basic256(const UA_SecurityPolicy *securityPolicy,
- Basic256_ChannelContext *cc,
+asym_encrypt_sp_basic256(Basic256_ChannelContext *cc,
UA_ByteString *data) {
- if(securityPolicy == NULL || cc == NULL || data == NULL)
+ if(cc == NULL || data == NULL)
return UA_STATUSCODE_BADINTERNALERROR;
- const size_t plainTextBlockSize = securityPolicy->asymmetricModule.cryptoModule.
- encryptionAlgorithm.getRemotePlainTextBlockSize(securityPolicy, cc);
+ const size_t plainTextBlockSize = asym_getRemotePlainTextBlockSize_sp_basic256(cc);
mbedtls_rsa_context *remoteRsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk);
mbedtls_rsa_set_padding(remoteRsaContext, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA1);
@@ -59779,39 +67825,34 @@ asym_encrypt_sp_basic256(const UA_SecurityPolicy *securityPolicy,
/* AsymmetricEncryptionAlgorithm_RSA-OAEP-SHA1 */
static UA_StatusCode
-asym_decrypt_sp_basic256(const UA_SecurityPolicy *securityPolicy,
- Basic256_ChannelContext *cc,
+asym_decrypt_sp_basic256(Basic256_ChannelContext *cc,
UA_ByteString *data) {
- if(securityPolicy == NULL || cc == NULL || data == NULL)
+ if(cc == NULL || data == NULL)
return UA_STATUSCODE_BADINTERNALERROR;
return mbedtls_decrypt_rsaOaep(&cc->policyContext->localPrivateKey,
&cc->policyContext->drbgContext, data);
}
static size_t
-asym_getLocalEncryptionKeyLength_sp_basic256(const UA_SecurityPolicy *securityPolicy,
- const Basic256_ChannelContext *cc) {
+asym_getLocalEncryptionKeyLength_sp_basic256(const Basic256_ChannelContext *cc) {
return mbedtls_pk_get_len(&cc->policyContext->localPrivateKey) * 8;
}
static size_t
-asym_getRemoteEncryptionKeyLength_sp_basic256(const UA_SecurityPolicy *securityPolicy,
- const Basic256_ChannelContext *cc) {
+asym_getRemoteEncryptionKeyLength_sp_basic256(const Basic256_ChannelContext *cc) {
return mbedtls_pk_get_len(&cc->remoteCertificate.pk) * 8;
}
static size_t
-asym_getRemoteBlockSize_sp_basic256(const UA_SecurityPolicy *securityPolicy,
- const Basic256_ChannelContext *cc) {
+asym_getRemoteBlockSize_sp_basic256(const Basic256_ChannelContext *cc) {
+#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
mbedtls_rsa_context *const rsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk);
return rsaContext->len;
-}
-
-static size_t
-asym_getRemotePlainTextBlockSize_sp_basic256(const UA_SecurityPolicy *securityPolicy,
- const Basic256_ChannelContext *cc) {
- mbedtls_rsa_context *const rsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk);
- return rsaContext->len - UA_SECURITYPOLICY_BASIC256SHA1_RSAPADDING_LEN;
+#else
+ if(cc == NULL)
+ return 0;
+ return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->remoteCertificate.pk));
+#endif
}
static UA_StatusCode
@@ -59841,22 +67882,17 @@ asymmetricModule_compareCertificateThumbprint_sp_basic256(const UA_SecurityPolic
/*******************/
static UA_StatusCode
-sym_verify_sp_basic256(const UA_SecurityPolicy *securityPolicy,
- Basic256_ChannelContext *cc,
+sym_verify_sp_basic256(Basic256_ChannelContext *cc,
const UA_ByteString *message,
const UA_ByteString *signature) {
- if(securityPolicy == NULL || cc == NULL || message == NULL || signature == NULL)
+ if(cc == NULL || message == NULL || signature == NULL)
return UA_STATUSCODE_BADINTERNALERROR;
/* Compute MAC */
- if(signature->length != UA_SHA1_LENGTH) {
- UA_LOG_ERROR(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY,
- "Signature size does not have the desired size defined by the security policy");
+ if(signature->length != UA_SHA1_LENGTH)
return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
- }
- Basic256_PolicyContext *pc =
- (Basic256_PolicyContext *)securityPolicy->policyContext;
+ Basic256_PolicyContext *pc = cc->policyContext;
unsigned char mac[UA_SHA1_LENGTH];
mbedtls_hmac(&pc->sha1MdContext, &cc->remoteSymSigningKey, message, mac);
@@ -59868,10 +67904,8 @@ sym_verify_sp_basic256(const UA_SecurityPolicy *securityPolicy,
}
static UA_StatusCode
-sym_sign_sp_basic256(const UA_SecurityPolicy *securityPolicy,
- const Basic256_ChannelContext *cc,
- const UA_ByteString *message,
- UA_ByteString *signature) {
+sym_sign_sp_basic256(const Basic256_ChannelContext *cc,
+ const UA_ByteString *message, UA_ByteString *signature) {
if(signature->length != UA_SHA1_LENGTH)
return UA_STATUSCODE_BADINTERNALERROR;
@@ -59881,57 +67915,42 @@ sym_sign_sp_basic256(const UA_SecurityPolicy *securityPolicy,
}
static size_t
-sym_getSignatureSize_sp_basic256(const UA_SecurityPolicy *securityPolicy,
- const void *channelContext) {
+sym_getSignatureSize_sp_basic256(const void *channelContext) {
return UA_SHA1_LENGTH;
}
static size_t
-sym_getSigningKeyLength_sp_basic256(const UA_SecurityPolicy *const securityPolicy,
- const void *const channelContext) {
+sym_getSigningKeyLength_sp_basic256(const void *const channelContext) {
return UA_BASIC256_SYM_SIGNING_KEY_LENGTH;
}
static size_t
-sym_getEncryptionKeyLength_sp_basic256(const UA_SecurityPolicy *securityPolicy,
- const void *channelContext) {
+sym_getEncryptionKeyLength_sp_basic256(const void *channelContext) {
return UA_SECURITYPOLICY_BASIC256_SYM_KEY_LENGTH;
}
static size_t
-sym_getEncryptionBlockSize_sp_basic256(const UA_SecurityPolicy *const securityPolicy,
- const void *const channelContext) {
+sym_getEncryptionBlockSize_sp_basic256(const void *const channelContext) {
return UA_SECURITYPOLICY_BASIC256_SYM_ENCRYPTION_BLOCK_SIZE;
}
static size_t
-sym_getPlainTextBlockSize_sp_basic256(const UA_SecurityPolicy *const securityPolicy,
- const void *const channelContext) {
+sym_getPlainTextBlockSize_sp_basic256(const void *const channelContext) {
return UA_SECURITYPOLICY_BASIC256_SYM_PLAIN_TEXT_BLOCK_SIZE;
}
static UA_StatusCode
-sym_encrypt_sp_basic256(const UA_SecurityPolicy *securityPolicy,
- const Basic256_ChannelContext *cc,
- UA_ByteString *data) {
- if(securityPolicy == NULL || cc == NULL || data == NULL)
+sym_encrypt_sp_basic256(const Basic256_ChannelContext *cc,
+ UA_ByteString *data) {
+ if(cc == NULL || data == NULL)
return UA_STATUSCODE_BADINTERNALERROR;
- if(cc->localSymIv.length !=
- securityPolicy->symmetricModule.cryptoModule.encryptionAlgorithm.
- getLocalBlockSize(securityPolicy, cc))
+ if(cc->localSymIv.length != UA_SECURITYPOLICY_BASIC256_SYM_ENCRYPTION_BLOCK_SIZE)
return UA_STATUSCODE_BADINTERNALERROR;
- size_t plainTextBlockSize =
- securityPolicy->symmetricModule.cryptoModule.encryptionAlgorithm.
- getLocalPlainTextBlockSize(securityPolicy, cc);
-
- if(data->length % plainTextBlockSize != 0) {
- UA_LOG_ERROR(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY,
- "Length of data to encrypt is not a multiple of the plain text block size."
- "Padding might not have been calculated appropriately.");
+ size_t plainTextBlockSize = UA_SECURITYPOLICY_BASIC256_SYM_PLAIN_TEXT_BLOCK_SIZE;
+ if(data->length % plainTextBlockSize != 0)
return UA_STATUSCODE_BADINTERNALERROR;
- }
/* Keylength in bits */
unsigned int keylength = (unsigned int)(cc->localSymEncryptingKey.length * 8);
@@ -59949,29 +67968,22 @@ sym_encrypt_sp_basic256(const UA_SecurityPolicy *securityPolicy,
ivCopy.data, data->data, data->data);
if(mbedErr)
retval = UA_STATUSCODE_BADINTERNALERROR;
- UA_ByteString_deleteMembers(&ivCopy);
+ UA_ByteString_clear(&ivCopy);
return retval;
}
static UA_StatusCode
-sym_decrypt_sp_basic256(const UA_SecurityPolicy *securityPolicy,
- const Basic256_ChannelContext *cc,
- UA_ByteString *data) {
- if(securityPolicy == NULL || cc == NULL || data == NULL)
+sym_decrypt_sp_basic256(const Basic256_ChannelContext *cc,
+ UA_ByteString *data) {
+ if(cc == NULL || data == NULL)
return UA_STATUSCODE_BADINTERNALERROR;
- size_t encryptionBlockSize =
- securityPolicy->symmetricModule.cryptoModule.encryptionAlgorithm.
- getRemoteBlockSize(securityPolicy, cc);
-
+ size_t encryptionBlockSize = UA_SECURITYPOLICY_BASIC256_SYM_ENCRYPTION_BLOCK_SIZE;
if(cc->remoteSymIv.length != encryptionBlockSize)
return UA_STATUSCODE_BADINTERNALERROR;
- if(data->length % encryptionBlockSize != 0) {
- UA_LOG_ERROR(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY,
- "Length of data to decrypt is not a multiple of the encryptingBlock size.");
+ if(data->length % encryptionBlockSize != 0)
return UA_STATUSCODE_BADINTERNALERROR;
- }
unsigned int keylength = (unsigned int)(cc->remoteSymEncryptingKey.length * 8);
mbedtls_aes_context aesContext;
@@ -59988,36 +68000,27 @@ sym_decrypt_sp_basic256(const UA_SecurityPolicy *securityPolicy,
ivCopy.data, data->data, data->data);
if(mbedErr)
retval = UA_STATUSCODE_BADINTERNALERROR;
- UA_ByteString_deleteMembers(&ivCopy);
+ UA_ByteString_clear(&ivCopy);
return retval;
}
static UA_StatusCode
-sym_generateKey_sp_basic256(const UA_SecurityPolicy *securityPolicy,
- const UA_ByteString *secret, const UA_ByteString *seed,
- UA_ByteString *out) {
- if(securityPolicy == NULL || secret == NULL || seed == NULL || out == NULL)
+sym_generateKey_sp_basic256(void *policyContext, const UA_ByteString *secret,
+ const UA_ByteString *seed, UA_ByteString *out) {
+ if(secret == NULL || seed == NULL || out == NULL)
return UA_STATUSCODE_BADINTERNALERROR;
-
- Basic256_PolicyContext *pc =
- (Basic256_PolicyContext *)securityPolicy->policyContext;
-
+ Basic256_PolicyContext *pc = (Basic256_PolicyContext *)policyContext;
return mbedtls_generateKey(&pc->sha1MdContext, secret, seed, out);
}
static UA_StatusCode
-sym_generateNonce_sp_basic256(const UA_SecurityPolicy *securityPolicy,
- UA_ByteString *out) {
- if(securityPolicy == NULL || securityPolicy->policyContext == NULL || out == NULL)
+sym_generateNonce_sp_basic256(void *policyContext, UA_ByteString *out) {
+ if(out == NULL)
return UA_STATUSCODE_BADINTERNALERROR;
-
- Basic256_PolicyContext *pc =
- (Basic256_PolicyContext *)securityPolicy->policyContext;
-
+ Basic256_PolicyContext *pc = (Basic256_PolicyContext *)policyContext;
int mbedErr = mbedtls_ctr_drbg_random(&pc->drbgContext, out->data, out->length);
if(mbedErr)
return UA_STATUSCODE_BADUNEXPECTEDERROR;
-
return UA_STATUSCODE_GOOD;
}
@@ -60039,9 +68042,15 @@ parseRemoteCertificate_sp_basic256(Basic256_ChannelContext *cc,
return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
/* Check the key length */
+#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
mbedtls_rsa_context *rsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk);
if(rsaContext->len < UA_SECURITYPOLICY_BASIC256_MINASYMKEYLENGTH ||
rsaContext->len > UA_SECURITYPOLICY_BASIC256_MAXASYMKEYLENGTH)
+#else
+ size_t keylen = mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->remoteCertificate.pk));
+ if(keylen < UA_SECURITYPOLICY_BASIC256_MINASYMKEYLENGTH ||
+ keylen > UA_SECURITYPOLICY_BASIC256_MAXASYMKEYLENGTH)
+#endif
return UA_STATUSCODE_BADCERTIFICATEUSENOTALLOWED;
return UA_STATUSCODE_GOOD;
@@ -60049,13 +68058,13 @@ parseRemoteCertificate_sp_basic256(Basic256_ChannelContext *cc,
static void
channelContext_deleteContext_sp_basic256(Basic256_ChannelContext *cc) {
- UA_ByteString_deleteMembers(&cc->localSymSigningKey);
- UA_ByteString_deleteMembers(&cc->localSymEncryptingKey);
- UA_ByteString_deleteMembers(&cc->localSymIv);
+ UA_ByteString_clear(&cc->localSymSigningKey);
+ UA_ByteString_clear(&cc->localSymEncryptingKey);
+ UA_ByteString_clear(&cc->localSymIv);
- UA_ByteString_deleteMembers(&cc->remoteSymSigningKey);
- UA_ByteString_deleteMembers(&cc->remoteSymEncryptingKey);
- UA_ByteString_deleteMembers(&cc->remoteSymIv);
+ UA_ByteString_clear(&cc->remoteSymSigningKey);
+ UA_ByteString_clear(&cc->remoteSymEncryptingKey);
+ UA_ByteString_clear(&cc->remoteSymIv);
mbedtls_x509_crt_free(&cc->remoteCertificate);
@@ -60104,7 +68113,7 @@ channelContext_setLocalSymEncryptingKey_sp_basic256(Basic256_ChannelContext *cc,
if(key == NULL || cc == NULL)
return UA_STATUSCODE_BADINTERNALERROR;
- UA_ByteString_deleteMembers(&cc->localSymEncryptingKey);
+ UA_ByteString_clear(&cc->localSymEncryptingKey);
return UA_ByteString_copy(key, &cc->localSymEncryptingKey);
}
@@ -60114,7 +68123,7 @@ channelContext_setLocalSymSigningKey_sp_basic256(Basic256_ChannelContext *cc,
if(key == NULL || cc == NULL)
return UA_STATUSCODE_BADINTERNALERROR;
- UA_ByteString_deleteMembers(&cc->localSymSigningKey);
+ UA_ByteString_clear(&cc->localSymSigningKey);
return UA_ByteString_copy(key, &cc->localSymSigningKey);
}
@@ -60125,7 +68134,7 @@ channelContext_setLocalSymIv_sp_basic256(Basic256_ChannelContext *cc,
if(iv == NULL || cc == NULL)
return UA_STATUSCODE_BADINTERNALERROR;
- UA_ByteString_deleteMembers(&cc->localSymIv);
+ UA_ByteString_clear(&cc->localSymIv);
return UA_ByteString_copy(iv, &cc->localSymIv);
}
@@ -60135,7 +68144,7 @@ channelContext_setRemoteSymEncryptingKey_sp_basic256(Basic256_ChannelContext *cc
if(key == NULL || cc == NULL)
return UA_STATUSCODE_BADINTERNALERROR;
- UA_ByteString_deleteMembers(&cc->remoteSymEncryptingKey);
+ UA_ByteString_clear(&cc->remoteSymEncryptingKey);
return UA_ByteString_copy(key, &cc->remoteSymEncryptingKey);
}
@@ -60145,7 +68154,7 @@ channelContext_setRemoteSymSigningKey_sp_basic256(Basic256_ChannelContext *cc,
if(key == NULL || cc == NULL)
return UA_STATUSCODE_BADINTERNALERROR;
- UA_ByteString_deleteMembers(&cc->remoteSymSigningKey);
+ UA_ByteString_clear(&cc->remoteSymSigningKey);
return UA_ByteString_copy(key, &cc->remoteSymSigningKey);
}
@@ -60155,7 +68164,7 @@ channelContext_setRemoteSymIv_sp_basic256(Basic256_ChannelContext *cc,
if(iv == NULL || cc == NULL)
return UA_STATUSCODE_BADINTERNALERROR;
- UA_ByteString_deleteMembers(&cc->remoteSymIv);
+ UA_ByteString_clear(&cc->remoteSymIv);
return UA_ByteString_copy(iv, &cc->remoteSymIv);
}
@@ -60185,7 +68194,7 @@ clear_sp_basic256(UA_SecurityPolicy *securityPolicy) {
if(securityPolicy == NULL)
return;
- UA_ByteString_deleteMembers(&securityPolicy->localCertificate);
+ UA_ByteString_clear(&securityPolicy->localCertificate);
if(securityPolicy->policyContext == NULL)
return;
@@ -60198,7 +68207,7 @@ clear_sp_basic256(UA_SecurityPolicy *securityPolicy) {
mbedtls_entropy_free(&pc->entropyContext);
mbedtls_pk_free(&pc->localPrivateKey);
mbedtls_md_free(&pc->sha1MdContext);
- UA_ByteString_deleteMembers(&pc->localCertThumbprint);
+ UA_ByteString_clear(&pc->localCertThumbprint);
UA_LOG_DEBUG(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY,
"Deleted members of EndpointContext for sp_basic256");
@@ -60220,7 +68229,7 @@ updateCertificateAndPrivateKey_sp_basic256(UA_SecurityPolicy *securityPolicy,
Basic256_PolicyContext *pc = (Basic256_PolicyContext *)
securityPolicy->policyContext;
- UA_ByteString_deleteMembers(&securityPolicy->localCertificate);
+ UA_ByteString_clear(&securityPolicy->localCertificate);
UA_StatusCode retval = UA_mbedTLS_LoadLocalCertificate(&newCertificate, &securityPolicy->localCertificate);
@@ -60231,7 +68240,7 @@ updateCertificateAndPrivateKey_sp_basic256(UA_SecurityPolicy *securityPolicy,
mbedtls_pk_free(&pc->localPrivateKey);
mbedtls_pk_init(&pc->localPrivateKey);
- int mbedErr = UA_mbedTLS_LoadPrivateKey(&newPrivateKey, &pc->localPrivateKey);
+ int mbedErr = UA_mbedTLS_LoadPrivateKey(&newPrivateKey, &pc->localPrivateKey, &pc->entropyContext);
if(mbedErr) {
retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
@@ -60290,10 +68299,8 @@ policyContext_newContext_sp_basic256(UA_SecurityPolicy *securityPolicy,
goto error;
}
- /* Add the system entropy source */
- mbedErr = mbedtls_entropy_add_source(&pc->entropyContext,
- MBEDTLS_ENTROPY_POLL_METHOD, NULL, 0,
- MBEDTLS_ENTROPY_SOURCE_STRONG);
+ mbedErr = mbedtls_entropy_self_test(0);
+
if(mbedErr) {
retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
goto error;
@@ -60310,7 +68317,7 @@ policyContext_newContext_sp_basic256(UA_SecurityPolicy *securityPolicy,
}
/* Set the private key */
- mbedErr = UA_mbedTLS_LoadPrivateKey(&localPrivateKey, &pc->localPrivateKey);
+ mbedErr = UA_mbedTLS_LoadPrivateKey(&localPrivateKey, &pc->localPrivateKey, &pc->entropyContext);
if(mbedErr) {
retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
goto error;
@@ -60359,15 +68366,13 @@ UA_SecurityPolicy_Basic256(UA_SecurityPolicy *policy, const UA_ByteString localC
asym_signatureAlgorithm->uri =
UA_STRING("http://www.w3.org/2000/09/xmldsig#rsa-sha1\0");
asym_signatureAlgorithm->verify =
- (UA_StatusCode (*)(const UA_SecurityPolicy *, void *,
- const UA_ByteString *, const UA_ByteString *))asym_verify_sp_basic256;
+ (UA_StatusCode (*)(void *, const UA_ByteString *, const UA_ByteString *))asym_verify_sp_basic256;
asym_signatureAlgorithm->sign =
- (UA_StatusCode (*)(const UA_SecurityPolicy *, void *,
- const UA_ByteString *, UA_ByteString *))asym_sign_sp_basic256;
+ (UA_StatusCode (*)(void *, const UA_ByteString *, UA_ByteString *))asym_sign_sp_basic256;
asym_signatureAlgorithm->getLocalSignatureSize =
- (size_t (*)(const UA_SecurityPolicy *, const void *))asym_getLocalSignatureSize_sp_basic256;
+ (size_t (*)(const void *))asym_getLocalSignatureSize_sp_basic256;
asym_signatureAlgorithm->getRemoteSignatureSize =
- (size_t (*)(const UA_SecurityPolicy *, const void *))asym_getRemoteSignatureSize_sp_basic256;
+ (size_t (*)(const void *))asym_getRemoteSignatureSize_sp_basic256;
asym_signatureAlgorithm->getLocalKeyLength = NULL; // TODO: Write function
asym_signatureAlgorithm->getRemoteKeyLength = NULL; // TODO: Write function
@@ -60375,20 +68380,17 @@ UA_SecurityPolicy_Basic256(UA_SecurityPolicy *policy, const UA_ByteString localC
&asymmetricModule->cryptoModule.encryptionAlgorithm;
asym_encryptionAlgorithm->uri = UA_STRING("http://www.w3.org/2001/04/xmlenc#rsa-oaep\0");
asym_encryptionAlgorithm->encrypt =
- (UA_StatusCode(*)(const UA_SecurityPolicy *, void *, UA_ByteString *))asym_encrypt_sp_basic256;
+ (UA_StatusCode(*)(void *, UA_ByteString *))asym_encrypt_sp_basic256;
asym_encryptionAlgorithm->decrypt =
- (UA_StatusCode(*)(const UA_SecurityPolicy *, void *, UA_ByteString *))
- asym_decrypt_sp_basic256;
+ (UA_StatusCode(*)(void *, UA_ByteString *))asym_decrypt_sp_basic256;
asym_encryptionAlgorithm->getLocalKeyLength =
- (size_t (*)(const UA_SecurityPolicy *, const void *))asym_getLocalEncryptionKeyLength_sp_basic256;
+ (size_t (*)(const void *))asym_getLocalEncryptionKeyLength_sp_basic256;
asym_encryptionAlgorithm->getRemoteKeyLength =
- (size_t (*)(const UA_SecurityPolicy *, const void *))asym_getRemoteEncryptionKeyLength_sp_basic256;
- asym_encryptionAlgorithm->getLocalBlockSize = NULL; // TODO: Write function
- asym_encryptionAlgorithm->getRemoteBlockSize = (size_t (*)(const UA_SecurityPolicy *,
- const void *))asym_getRemoteBlockSize_sp_basic256;
- asym_encryptionAlgorithm->getLocalPlainTextBlockSize = NULL; // TODO: Write function
+ (size_t (*)(const void *))asym_getRemoteEncryptionKeyLength_sp_basic256;
+ asym_encryptionAlgorithm->getRemoteBlockSize =
+ (size_t (*)(const void *))asym_getRemoteBlockSize_sp_basic256;
asym_encryptionAlgorithm->getRemotePlainTextBlockSize =
- (size_t (*)(const UA_SecurityPolicy *, const void *))asym_getRemotePlainTextBlockSize_sp_basic256;
+ (size_t (*)(const void *))asym_getRemotePlainTextBlockSize_sp_basic256;
asymmetricModule->makeCertificateThumbprint = asym_makeThumbprint_sp_basic256;
asymmetricModule->compareCertificateThumbprint =
@@ -60403,37 +68405,30 @@ UA_SecurityPolicy_Basic256(UA_SecurityPolicy *policy, const UA_ByteString localC
sym_signatureAlgorithm->uri =
UA_STRING("http://www.w3.org/2000/09/xmldsig#hmac-sha1\0");
sym_signatureAlgorithm->verify =
- (UA_StatusCode (*)(const UA_SecurityPolicy *, void *, const UA_ByteString *,
+ (UA_StatusCode (*)(void *, const UA_ByteString *,
const UA_ByteString *))sym_verify_sp_basic256;
sym_signatureAlgorithm->sign =
- (UA_StatusCode (*)(const UA_SecurityPolicy *, void *,
- const UA_ByteString *, UA_ByteString *))sym_sign_sp_basic256;
+ (UA_StatusCode (*)(void *, const UA_ByteString *, UA_ByteString *))sym_sign_sp_basic256;
sym_signatureAlgorithm->getLocalSignatureSize = sym_getSignatureSize_sp_basic256;
sym_signatureAlgorithm->getRemoteSignatureSize = sym_getSignatureSize_sp_basic256;
sym_signatureAlgorithm->getLocalKeyLength =
- (size_t (*)(const UA_SecurityPolicy *,
- const void *))sym_getSigningKeyLength_sp_basic256;
+ (size_t (*)(const void *))sym_getSigningKeyLength_sp_basic256;
sym_signatureAlgorithm->getRemoteKeyLength =
- (size_t (*)(const UA_SecurityPolicy *,
- const void *))sym_getSigningKeyLength_sp_basic256;
+ (size_t (*)(const void *))sym_getSigningKeyLength_sp_basic256;
UA_SecurityPolicyEncryptionAlgorithm *sym_encryptionAlgorithm =
&symmetricModule->cryptoModule.encryptionAlgorithm;
sym_encryptionAlgorithm->uri = UA_STRING("http://www.w3.org/2001/04/xmlenc#aes256-cbc\0");
sym_encryptionAlgorithm->encrypt =
- (UA_StatusCode(*)(const UA_SecurityPolicy *, void *, UA_ByteString *))sym_encrypt_sp_basic256;
+ (UA_StatusCode(*)(void *, UA_ByteString *))sym_encrypt_sp_basic256;
sym_encryptionAlgorithm->decrypt =
- (UA_StatusCode(*)(const UA_SecurityPolicy *, void *, UA_ByteString *))sym_decrypt_sp_basic256;
+ (UA_StatusCode(*)(void *, UA_ByteString *))sym_decrypt_sp_basic256;
sym_encryptionAlgorithm->getLocalKeyLength = sym_getEncryptionKeyLength_sp_basic256;
sym_encryptionAlgorithm->getRemoteKeyLength = sym_getEncryptionKeyLength_sp_basic256;
- sym_encryptionAlgorithm->getLocalBlockSize =
- (size_t (*)(const UA_SecurityPolicy *, const void *))sym_getEncryptionBlockSize_sp_basic256;
sym_encryptionAlgorithm->getRemoteBlockSize =
- (size_t (*)(const UA_SecurityPolicy *, const void *))sym_getEncryptionBlockSize_sp_basic256;
- sym_encryptionAlgorithm->getLocalPlainTextBlockSize =
- (size_t (*)(const UA_SecurityPolicy *, const void *))sym_getPlainTextBlockSize_sp_basic256;
+ (size_t (*)(const void *))sym_getEncryptionBlockSize_sp_basic256;
sym_encryptionAlgorithm->getRemotePlainTextBlockSize =
- (size_t (*)(const UA_SecurityPolicy *, const void *))sym_getPlainTextBlockSize_sp_basic256;
+ (size_t (*)(const void *))sym_getPlainTextBlockSize_sp_basic256;
symmetricModule->secureChannelNonceLength = 32;
// Use the same signature algorithm as the asymmetric component for certificate signing (see standard)
@@ -60473,7 +68468,7 @@ UA_SecurityPolicy_Basic256(UA_SecurityPolicy *policy, const UA_ByteString localC
#endif
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/plugins/securityPolicies/ua_securitypolicy_basic256sha256.c" ***********************************/
+/**** amalgamated original file "/plugins/crypto/mbedtls/ua_securitypolicy_basic256sha256.c" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -60493,7 +68488,6 @@ UA_SecurityPolicy_Basic256(UA_SecurityPolicy *policy, const UA_ByteString localC
#include <mbedtls/aes.h>
#include <mbedtls/ctr_drbg.h>
#include <mbedtls/entropy.h>
-#include <mbedtls/entropy_poll.h>
#include <mbedtls/error.h>
#include <mbedtls/md.h>
#include <mbedtls/sha1.h>
@@ -60546,15 +68540,14 @@ typedef struct {
/* VERIFY AsymmetricSignatureAlgorithm_RSA-PKCS15-SHA2-256 */
static UA_StatusCode
-asym_verify_sp_basic256sha256(const UA_SecurityPolicy *securityPolicy,
- Basic256Sha256_ChannelContext *cc,
+asym_verify_sp_basic256sha256(Basic256Sha256_ChannelContext *cc,
const UA_ByteString *message,
const UA_ByteString *signature) {
- if(securityPolicy == NULL || message == NULL || signature == NULL || cc == NULL)
+ if(message == NULL || signature == NULL || cc == NULL)
return UA_STATUSCODE_BADINTERNALERROR;
unsigned char hash[UA_SHA256_LENGTH];
-#if MBEDTLS_VERSION_NUMBER >= 0x02070000
+#if MBEDTLS_VERSION_NUMBER >= 0x02070000 && MBEDTLS_VERSION_NUMBER < 0x03000000
// TODO check return status
mbedtls_sha256_ret(message->data, message->length, hash, 0);
#else
@@ -60582,15 +68575,14 @@ asym_verify_sp_basic256sha256(const UA_SecurityPolicy *securityPolicy,
/* AsymmetricSignatureAlgorithm_RSA-PKCS15-SHA2-256 */
static UA_StatusCode
-asym_sign_sp_basic256sha256(const UA_SecurityPolicy *securityPolicy,
- Basic256Sha256_ChannelContext *cc,
+asym_sign_sp_basic256sha256(Basic256Sha256_ChannelContext *cc,
const UA_ByteString *message,
UA_ByteString *signature) {
- if(securityPolicy == NULL || message == NULL || signature == NULL || cc == NULL)
+ if(message == NULL || signature == NULL || cc == NULL)
return UA_STATUSCODE_BADINTERNALERROR;
unsigned char hash[UA_SHA256_LENGTH];
-#if MBEDTLS_VERSION_NUMBER >= 0x02070000
+#if MBEDTLS_VERSION_NUMBER >= 0x02070000 && MBEDTLS_VERSION_NUMBER < 0x03000000
// TODO check return status
mbedtls_sha256_ret(message->data, message->length, hash, 0);
#else
@@ -60608,6 +68600,9 @@ asym_sign_sp_basic256sha256(const UA_SecurityPolicy *securityPolicy,
int mbedErr = mbedtls_pk_sign(&pc->localPrivateKey,
MBEDTLS_MD_SHA256, hash,
UA_SHA256_LENGTH, signature->data,
+#if MBEDTLS_VERSION_NUMBER >= 0x03000000
+ signature->length,
+#endif
&sigLen, mbedtls_ctr_drbg_random,
&pc->drbgContext);
if(mbedErr)
@@ -60616,33 +68611,61 @@ asym_sign_sp_basic256sha256(const UA_SecurityPolicy *securityPolicy,
}
static size_t
-asym_getLocalSignatureSize_sp_basic256sha256(const UA_SecurityPolicy *securityPolicy,
- const Basic256Sha256_ChannelContext *cc) {
- if(securityPolicy == NULL || cc == NULL)
+asym_getLocalSignatureSize_sp_basic256sha256(const Basic256Sha256_ChannelContext *cc) {
+ if(cc == NULL)
return 0;
-
+#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
return mbedtls_pk_rsa(cc->policyContext->localPrivateKey)->len;
+#else
+ return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->policyContext->localPrivateKey));
+#endif
}
static size_t
-asym_getRemoteSignatureSize_sp_basic256sha256(const UA_SecurityPolicy *securityPolicy,
- const Basic256Sha256_ChannelContext *cc) {
- if(securityPolicy == NULL || cc == NULL)
+asym_getRemoteSignatureSize_sp_basic256sha256(const Basic256Sha256_ChannelContext *cc) {
+ if(cc == NULL)
return 0;
-
+#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
return mbedtls_pk_rsa(cc->remoteCertificate.pk)->len;
+#else
+ return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->remoteCertificate.pk));
+#endif
+}
+
+static size_t
+asym_getRemoteBlockSize_sp_basic256sha256(const Basic256Sha256_ChannelContext *cc) {
+#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
+ mbedtls_rsa_context *const rsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk);
+ return rsaContext->len;
+#else
+ if(cc == NULL)
+ return 0;
+ return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->remoteCertificate.pk));
+#endif
+}
+
+static size_t
+asym_getRemotePlainTextBlockSize_sp_basic256sha256(const Basic256Sha256_ChannelContext *cc) {
+#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
+ mbedtls_rsa_context *const rsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk);
+ return rsaContext->len - UA_SECURITYPOLICY_BASIC256SHA256_RSAPADDING_LEN;
+#else
+ if(cc == NULL)
+ return 0;
+ return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->remoteCertificate.pk)) -
+ UA_SECURITYPOLICY_BASIC256SHA256_RSAPADDING_LEN;
+#endif
}
+
/* AsymmetricEncryptionAlgorithm_RSA-OAEP-SHA1 */
static UA_StatusCode
-asym_encrypt_sp_basic256sha256(const UA_SecurityPolicy *securityPolicy,
- Basic256Sha256_ChannelContext *cc,
+asym_encrypt_sp_basic256sha256(Basic256Sha256_ChannelContext *cc,
UA_ByteString *data) {
- if(securityPolicy == NULL || cc == NULL || data == NULL)
+ if(cc == NULL || data == NULL)
return UA_STATUSCODE_BADINTERNALERROR;
- const size_t plainTextBlockSize = securityPolicy->asymmetricModule.cryptoModule.
- encryptionAlgorithm.getRemotePlainTextBlockSize(securityPolicy, cc);
+ const size_t plainTextBlockSize = asym_getRemotePlainTextBlockSize_sp_basic256sha256(cc);
mbedtls_rsa_context *remoteRsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk);
mbedtls_rsa_set_padding(remoteRsaContext, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA1);
@@ -60653,41 +68676,24 @@ asym_encrypt_sp_basic256sha256(const UA_SecurityPolicy *securityPolicy,
/* AsymmetricEncryptionAlgorithm_RSA-OAEP-SHA1 */
static UA_StatusCode
-asym_decrypt_sp_basic256sha256(const UA_SecurityPolicy *securityPolicy,
- Basic256Sha256_ChannelContext *cc,
+asym_decrypt_sp_basic256sha256(Basic256Sha256_ChannelContext *cc,
UA_ByteString *data) {
- if(securityPolicy == NULL || cc == NULL || data == NULL)
+ if(cc == NULL || data == NULL)
return UA_STATUSCODE_BADINTERNALERROR;
return mbedtls_decrypt_rsaOaep(&cc->policyContext->localPrivateKey,
&cc->policyContext->drbgContext, data);
}
static size_t
-asym_getLocalEncryptionKeyLength_sp_basic256sha256(const UA_SecurityPolicy *securityPolicy,
- const Basic256Sha256_ChannelContext *cc) {
+asym_getLocalEncryptionKeyLength_sp_basic256sha256(const Basic256Sha256_ChannelContext *cc) {
return mbedtls_pk_get_len(&cc->policyContext->localPrivateKey) * 8;
}
static size_t
-asym_getRemoteEncryptionKeyLength_sp_basic256sha256(const UA_SecurityPolicy *securityPolicy,
- const Basic256Sha256_ChannelContext *cc) {
+asym_getRemoteEncryptionKeyLength_sp_basic256sha256(const Basic256Sha256_ChannelContext *cc) {
return mbedtls_pk_get_len(&cc->remoteCertificate.pk) * 8;
}
-static size_t
-asym_getRemoteBlockSize_sp_basic256sha256(const UA_SecurityPolicy *securityPolicy,
- const Basic256Sha256_ChannelContext *cc) {
- mbedtls_rsa_context *const rsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk);
- return rsaContext->len;
-}
-
-static size_t
-asym_getRemotePlainTextBlockSize_sp_basic256sha256(const UA_SecurityPolicy *securityPolicy,
- const Basic256Sha256_ChannelContext *cc) {
- mbedtls_rsa_context *const rsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk);
- return rsaContext->len - UA_SECURITYPOLICY_BASIC256SHA256_RSAPADDING_LEN;
-}
-
static UA_StatusCode
asym_makeThumbprint_sp_basic256sha256(const UA_SecurityPolicy *securityPolicy,
const UA_ByteString *certificate,
@@ -60715,23 +68721,17 @@ asymmetricModule_compareCertificateThumbprint_sp_basic256sha256(const UA_Securit
/*******************/
static UA_StatusCode
-sym_verify_sp_basic256sha256(const UA_SecurityPolicy *securityPolicy,
- Basic256Sha256_ChannelContext *cc,
+sym_verify_sp_basic256sha256(Basic256Sha256_ChannelContext *cc,
const UA_ByteString *message,
const UA_ByteString *signature) {
- if(securityPolicy == NULL || cc == NULL || message == NULL || signature == NULL)
+ if(cc == NULL || message == NULL || signature == NULL)
return UA_STATUSCODE_BADINTERNALERROR;
/* Compute MAC */
- if(signature->length != UA_SHA256_LENGTH) {
- UA_LOG_ERROR(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY,
- "Signature size does not have the desired size defined by the security policy");
+ if(signature->length != UA_SHA256_LENGTH)
return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
- }
-
- Basic256Sha256_PolicyContext *pc =
- (Basic256Sha256_PolicyContext *)securityPolicy->policyContext;
+ Basic256Sha256_PolicyContext *pc = cc->policyContext;
unsigned char mac[UA_SHA256_LENGTH];
mbedtls_hmac(&pc->sha256MdContext, &cc->remoteSymSigningKey, message, mac);
@@ -60742,8 +68742,7 @@ sym_verify_sp_basic256sha256(const UA_SecurityPolicy *securityPolicy,
}
static UA_StatusCode
-sym_sign_sp_basic256sha256(const UA_SecurityPolicy *securityPolicy,
- const Basic256Sha256_ChannelContext *cc,
+sym_sign_sp_basic256sha256(const Basic256Sha256_ChannelContext *cc,
const UA_ByteString *message,
UA_ByteString *signature) {
if(signature->length != UA_SHA256_LENGTH)
@@ -60755,55 +68754,43 @@ sym_sign_sp_basic256sha256(const UA_SecurityPolicy *securityPolicy,
}
static size_t
-sym_getSignatureSize_sp_basic256sha256(const UA_SecurityPolicy *securityPolicy,
- const void *channelContext) {
+sym_getSignatureSize_sp_basic256sha256(const void *channelContext) {
return UA_SHA256_LENGTH;
}
static size_t
-sym_getSigningKeyLength_sp_basic256sha256(const UA_SecurityPolicy *const securityPolicy,
- const void *const channelContext) {
+sym_getSigningKeyLength_sp_basic256sha256(const void *channelContext) {
return UA_BASIC256SHA256_SYM_SIGNING_KEY_LENGTH;
}
static size_t
-sym_getEncryptionKeyLength_sp_basic256sha256(const UA_SecurityPolicy *securityPolicy,
- const void *channelContext) {
+sym_getEncryptionKeyLength_sp_basic256sha256(const void *channelContext) {
return UA_SECURITYPOLICY_BASIC256SHA256_SYM_KEY_LENGTH;
}
static size_t
-sym_getEncryptionBlockSize_sp_basic256sha256(const UA_SecurityPolicy *const securityPolicy,
- const void *const channelContext) {
+sym_getEncryptionBlockSize_sp_basic256sha256(const void *channelContext) {
return UA_SECURITYPOLICY_BASIC256SHA256_SYM_ENCRYPTION_BLOCK_SIZE;
}
static size_t
-sym_getPlainTextBlockSize_sp_basic256sha256(const UA_SecurityPolicy *const securityPolicy,
- const void *const channelContext) {
+sym_getPlainTextBlockSize_sp_basic256sha256(const void *channelContext) {
return UA_SECURITYPOLICY_BASIC256SHA256_SYM_PLAIN_TEXT_BLOCK_SIZE;
}
static UA_StatusCode
-sym_encrypt_sp_basic256sha256(const UA_SecurityPolicy *securityPolicy,
- const Basic256Sha256_ChannelContext *cc,
+sym_encrypt_sp_basic256sha256(const Basic256Sha256_ChannelContext *cc,
UA_ByteString *data) {
- if(securityPolicy == NULL || cc == NULL || data == NULL)
+ if(cc == NULL || data == NULL)
return UA_STATUSCODE_BADINTERNALERROR;
- if(cc->localSymIv.length != securityPolicy->symmetricModule.cryptoModule.
- encryptionAlgorithm.getLocalBlockSize(securityPolicy, cc))
+ if(cc->localSymIv.length != UA_SECURITYPOLICY_BASIC256SHA256_SYM_ENCRYPTION_BLOCK_SIZE)
return UA_STATUSCODE_BADINTERNALERROR;
- size_t plainTextBlockSize = securityPolicy->symmetricModule.cryptoModule.
- encryptionAlgorithm.getLocalPlainTextBlockSize(securityPolicy, cc);
+ size_t plainTextBlockSize = UA_SECURITYPOLICY_BASIC256SHA256_SYM_PLAIN_TEXT_BLOCK_SIZE;
- if(data->length % plainTextBlockSize != 0) {
- UA_LOG_ERROR(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY,
- "Length of data to encrypt is not a multiple of the plain text block size."
- "Padding might not have been calculated appropriately.");
+ if(data->length % plainTextBlockSize != 0)
return UA_STATUSCODE_BADINTERNALERROR;
- }
/* Keylength in bits */
unsigned int keylength = (unsigned int)(cc->localSymEncryptingKey.length * 8);
@@ -60821,28 +68808,22 @@ sym_encrypt_sp_basic256sha256(const UA_SecurityPolicy *securityPolicy,
ivCopy.data, data->data, data->data);
if(mbedErr)
retval = UA_STATUSCODE_BADINTERNALERROR;
- UA_ByteString_deleteMembers(&ivCopy);
+ UA_ByteString_clear(&ivCopy);
return retval;
}
static UA_StatusCode
-sym_decrypt_sp_basic256sha256(const UA_SecurityPolicy *securityPolicy,
- const Basic256Sha256_ChannelContext *cc,
+sym_decrypt_sp_basic256sha256(const Basic256Sha256_ChannelContext *cc,
UA_ByteString *data) {
- if(securityPolicy == NULL || cc == NULL || data == NULL)
+ if(cc == NULL || data == NULL)
return UA_STATUSCODE_BADINTERNALERROR;
- size_t encryptionBlockSize = securityPolicy->symmetricModule.cryptoModule.
- encryptionAlgorithm.getRemoteBlockSize(securityPolicy, cc);
-
+ size_t encryptionBlockSize = UA_SECURITYPOLICY_BASIC256SHA256_SYM_ENCRYPTION_BLOCK_SIZE;
if(cc->remoteSymIv.length != encryptionBlockSize)
return UA_STATUSCODE_BADINTERNALERROR;
- if(data->length % encryptionBlockSize != 0) {
- UA_LOG_ERROR(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY,
- "Length of data to decrypt is not a multiple of the encryptingBlock size.");
+ if(data->length % encryptionBlockSize != 0)
return UA_STATUSCODE_BADINTERNALERROR;
- }
unsigned int keylength = (unsigned int)(cc->remoteSymEncryptingKey.length * 8);
mbedtls_aes_context aesContext;
@@ -60859,31 +68840,24 @@ sym_decrypt_sp_basic256sha256(const UA_SecurityPolicy *securityPolicy,
ivCopy.data, data->data, data->data);
if(mbedErr)
retval = UA_STATUSCODE_BADINTERNALERROR;
- UA_ByteString_deleteMembers(&ivCopy);
+ UA_ByteString_clear(&ivCopy);
return retval;
}
static UA_StatusCode
-sym_generateKey_sp_basic256sha256(const UA_SecurityPolicy *securityPolicy,
- const UA_ByteString *secret, const UA_ByteString *seed,
- UA_ByteString *out) {
- if(securityPolicy == NULL || secret == NULL || seed == NULL || out == NULL)
+sym_generateKey_sp_basic256sha256(void *policyContext, const UA_ByteString *secret,
+ const UA_ByteString *seed, UA_ByteString *out) {
+ if(secret == NULL || seed == NULL || out == NULL)
return UA_STATUSCODE_BADINTERNALERROR;
-
- Basic256Sha256_PolicyContext *pc =
- (Basic256Sha256_PolicyContext *)securityPolicy->policyContext;
-
+ Basic256Sha256_PolicyContext *pc = (Basic256Sha256_PolicyContext *)policyContext;
return mbedtls_generateKey(&pc->sha256MdContext, secret, seed, out);
}
static UA_StatusCode
-sym_generateNonce_sp_basic256sha256(const UA_SecurityPolicy *securityPolicy,
- UA_ByteString *out) {
- if(securityPolicy == NULL || securityPolicy->policyContext == NULL || out == NULL)
+sym_generateNonce_sp_basic256sha256(void *policyContext, UA_ByteString *out) {
+ if(out == NULL)
return UA_STATUSCODE_BADINTERNALERROR;
-
- Basic256Sha256_PolicyContext *pc =
- (Basic256Sha256_PolicyContext *)securityPolicy->policyContext;
+ Basic256Sha256_PolicyContext *pc = (Basic256Sha256_PolicyContext *)policyContext;
int mbedErr = mbedtls_ctr_drbg_random(&pc->drbgContext, out->data, out->length);
if(mbedErr)
return UA_STATUSCODE_BADUNEXPECTEDERROR;
@@ -60908,9 +68882,15 @@ parseRemoteCertificate_sp_basic256sha256(Basic256Sha256_ChannelContext *cc,
return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
/* Check the key length */
+#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
mbedtls_rsa_context *rsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk);
if(rsaContext->len < UA_SECURITYPOLICY_BASIC256SHA256_MINASYMKEYLENGTH ||
rsaContext->len > UA_SECURITYPOLICY_BASIC256SHA256_MAXASYMKEYLENGTH)
+#else
+ size_t keylen = mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->remoteCertificate.pk));
+ if(keylen < UA_SECURITYPOLICY_BASIC256SHA256_MINASYMKEYLENGTH ||
+ keylen > UA_SECURITYPOLICY_BASIC256SHA256_MAXASYMKEYLENGTH)
+#endif
return UA_STATUSCODE_BADCERTIFICATEUSENOTALLOWED;
return UA_STATUSCODE_GOOD;
@@ -60918,13 +68898,13 @@ parseRemoteCertificate_sp_basic256sha256(Basic256Sha256_ChannelContext *cc,
static void
channelContext_deleteContext_sp_basic256sha256(Basic256Sha256_ChannelContext *cc) {
- UA_ByteString_deleteMembers(&cc->localSymSigningKey);
- UA_ByteString_deleteMembers(&cc->localSymEncryptingKey);
- UA_ByteString_deleteMembers(&cc->localSymIv);
+ UA_ByteString_clear(&cc->localSymSigningKey);
+ UA_ByteString_clear(&cc->localSymEncryptingKey);
+ UA_ByteString_clear(&cc->localSymIv);
- UA_ByteString_deleteMembers(&cc->remoteSymSigningKey);
- UA_ByteString_deleteMembers(&cc->remoteSymEncryptingKey);
- UA_ByteString_deleteMembers(&cc->remoteSymIv);
+ UA_ByteString_clear(&cc->remoteSymSigningKey);
+ UA_ByteString_clear(&cc->remoteSymEncryptingKey);
+ UA_ByteString_clear(&cc->remoteSymIv);
mbedtls_x509_crt_free(&cc->remoteCertificate);
@@ -60973,7 +68953,7 @@ channelContext_setLocalSymEncryptingKey_sp_basic256sha256(Basic256Sha256_Channel
if(key == NULL || cc == NULL)
return UA_STATUSCODE_BADINTERNALERROR;
- UA_ByteString_deleteMembers(&cc->localSymEncryptingKey);
+ UA_ByteString_clear(&cc->localSymEncryptingKey);
return UA_ByteString_copy(key, &cc->localSymEncryptingKey);
}
@@ -60983,7 +68963,7 @@ channelContext_setLocalSymSigningKey_sp_basic256sha256(Basic256Sha256_ChannelCon
if(key == NULL || cc == NULL)
return UA_STATUSCODE_BADINTERNALERROR;
- UA_ByteString_deleteMembers(&cc->localSymSigningKey);
+ UA_ByteString_clear(&cc->localSymSigningKey);
return UA_ByteString_copy(key, &cc->localSymSigningKey);
}
@@ -60994,7 +68974,7 @@ channelContext_setLocalSymIv_sp_basic256sha256(Basic256Sha256_ChannelContext *cc
if(iv == NULL || cc == NULL)
return UA_STATUSCODE_BADINTERNALERROR;
- UA_ByteString_deleteMembers(&cc->localSymIv);
+ UA_ByteString_clear(&cc->localSymIv);
return UA_ByteString_copy(iv, &cc->localSymIv);
}
@@ -61004,7 +68984,7 @@ channelContext_setRemoteSymEncryptingKey_sp_basic256sha256(Basic256Sha256_Channe
if(key == NULL || cc == NULL)
return UA_STATUSCODE_BADINTERNALERROR;
- UA_ByteString_deleteMembers(&cc->remoteSymEncryptingKey);
+ UA_ByteString_clear(&cc->remoteSymEncryptingKey);
return UA_ByteString_copy(key, &cc->remoteSymEncryptingKey);
}
@@ -61014,7 +68994,7 @@ channelContext_setRemoteSymSigningKey_sp_basic256sha256(Basic256Sha256_ChannelCo
if(key == NULL || cc == NULL)
return UA_STATUSCODE_BADINTERNALERROR;
- UA_ByteString_deleteMembers(&cc->remoteSymSigningKey);
+ UA_ByteString_clear(&cc->remoteSymSigningKey);
return UA_ByteString_copy(key, &cc->remoteSymSigningKey);
}
@@ -61024,7 +69004,7 @@ channelContext_setRemoteSymIv_sp_basic256sha256(Basic256Sha256_ChannelContext *c
if(iv == NULL || cc == NULL)
return UA_STATUSCODE_BADINTERNALERROR;
- UA_ByteString_deleteMembers(&cc->remoteSymIv);
+ UA_ByteString_clear(&cc->remoteSymIv);
return UA_ByteString_copy(iv, &cc->remoteSymIv);
}
@@ -61054,7 +69034,7 @@ clear_sp_basic256sha256(UA_SecurityPolicy *securityPolicy) {
if(securityPolicy == NULL)
return;
- UA_ByteString_deleteMembers(&securityPolicy->localCertificate);
+ UA_ByteString_clear(&securityPolicy->localCertificate);
if(securityPolicy->policyContext == NULL)
return;
@@ -61067,7 +69047,7 @@ clear_sp_basic256sha256(UA_SecurityPolicy *securityPolicy) {
mbedtls_entropy_free(&pc->entropyContext);
mbedtls_pk_free(&pc->localPrivateKey);
mbedtls_md_free(&pc->sha256MdContext);
- UA_ByteString_deleteMembers(&pc->localCertThumbprint);
+ UA_ByteString_clear(&pc->localCertThumbprint);
UA_LOG_DEBUG(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY,
"Deleted members of EndpointContext for sp_basic256sha256");
@@ -61089,7 +69069,7 @@ updateCertificateAndPrivateKey_sp_basic256sha256(UA_SecurityPolicy *securityPoli
Basic256Sha256_PolicyContext *pc =
(Basic256Sha256_PolicyContext *) securityPolicy->policyContext;
- UA_ByteString_deleteMembers(&securityPolicy->localCertificate);
+ UA_ByteString_clear(&securityPolicy->localCertificate);
UA_StatusCode retval = UA_mbedTLS_LoadLocalCertificate(&newCertificate, &securityPolicy->localCertificate);
@@ -61099,7 +69079,7 @@ updateCertificateAndPrivateKey_sp_basic256sha256(UA_SecurityPolicy *securityPoli
/* Set the new private key */
mbedtls_pk_free(&pc->localPrivateKey);
mbedtls_pk_init(&pc->localPrivateKey);
- int mbedErr = UA_mbedTLS_LoadPrivateKey(&newPrivateKey, &pc->localPrivateKey);
+ int mbedErr = UA_mbedTLS_LoadPrivateKey(&newPrivateKey, &pc->localPrivateKey, &pc->entropyContext);
if(mbedErr) {
retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
goto error;
@@ -61157,10 +69137,8 @@ policyContext_newContext_sp_basic256sha256(UA_SecurityPolicy *securityPolicy,
goto error;
}
- /* Add the system entropy source */
- mbedErr = mbedtls_entropy_add_source(&pc->entropyContext,
- MBEDTLS_ENTROPY_POLL_METHOD, NULL, 0,
- MBEDTLS_ENTROPY_SOURCE_STRONG);
+ mbedErr = mbedtls_entropy_self_test(0);
+
if(mbedErr) {
retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
goto error;
@@ -61177,7 +69155,7 @@ policyContext_newContext_sp_basic256sha256(UA_SecurityPolicy *securityPolicy,
}
/* Set the private key */
- mbedErr = UA_mbedTLS_LoadPrivateKey(&localPrivateKey, &pc->localPrivateKey);
+ mbedErr = UA_mbedTLS_LoadPrivateKey(&localPrivateKey, &pc->localPrivateKey, &pc->entropyContext);
if(mbedErr) {
retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
goto error;
@@ -61226,15 +69204,13 @@ UA_SecurityPolicy_Basic256Sha256(UA_SecurityPolicy *policy, const UA_ByteString
asym_signatureAlgorithm->uri =
UA_STRING("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256\0");
asym_signatureAlgorithm->verify =
- (UA_StatusCode (*)(const UA_SecurityPolicy *, void *,
- const UA_ByteString *, const UA_ByteString *))asym_verify_sp_basic256sha256;
+ (UA_StatusCode (*)(void *, const UA_ByteString *, const UA_ByteString *))asym_verify_sp_basic256sha256;
asym_signatureAlgorithm->sign =
- (UA_StatusCode (*)(const UA_SecurityPolicy *, void *,
- const UA_ByteString *, UA_ByteString *))asym_sign_sp_basic256sha256;
+ (UA_StatusCode (*)(void *, const UA_ByteString *, UA_ByteString *))asym_sign_sp_basic256sha256;
asym_signatureAlgorithm->getLocalSignatureSize =
- (size_t (*)(const UA_SecurityPolicy *, const void *))asym_getLocalSignatureSize_sp_basic256sha256;
+ (size_t (*)(const void *))asym_getLocalSignatureSize_sp_basic256sha256;
asym_signatureAlgorithm->getRemoteSignatureSize =
- (size_t (*)(const UA_SecurityPolicy *, const void *))asym_getRemoteSignatureSize_sp_basic256sha256;
+ (size_t (*)(const void *))asym_getRemoteSignatureSize_sp_basic256sha256;
asym_signatureAlgorithm->getLocalKeyLength = NULL; // TODO: Write function
asym_signatureAlgorithm->getRemoteKeyLength = NULL; // TODO: Write function
@@ -61242,20 +69218,18 @@ UA_SecurityPolicy_Basic256Sha256(UA_SecurityPolicy *policy, const UA_ByteString
&asymmetricModule->cryptoModule.encryptionAlgorithm;
asym_encryptionAlgorithm->uri = UA_STRING("http://www.w3.org/2001/04/xmlenc#rsa-oaep\0");
asym_encryptionAlgorithm->encrypt =
- (UA_StatusCode(*)(const UA_SecurityPolicy *, void *, UA_ByteString *))asym_encrypt_sp_basic256sha256;
+ (UA_StatusCode(*)(void *, UA_ByteString *))asym_encrypt_sp_basic256sha256;
asym_encryptionAlgorithm->decrypt =
- (UA_StatusCode(*)(const UA_SecurityPolicy *, void *, UA_ByteString *))
+ (UA_StatusCode(*)(void *, UA_ByteString *))
asym_decrypt_sp_basic256sha256;
asym_encryptionAlgorithm->getLocalKeyLength =
- (size_t (*)(const UA_SecurityPolicy *, const void *))asym_getLocalEncryptionKeyLength_sp_basic256sha256;
+ (size_t (*)(const void *))asym_getLocalEncryptionKeyLength_sp_basic256sha256;
asym_encryptionAlgorithm->getRemoteKeyLength =
- (size_t (*)(const UA_SecurityPolicy *, const void *))asym_getRemoteEncryptionKeyLength_sp_basic256sha256;
- asym_encryptionAlgorithm->getLocalBlockSize = NULL; // TODO: Write function
- asym_encryptionAlgorithm->getRemoteBlockSize = (size_t (*)(const UA_SecurityPolicy *,
- const void *))asym_getRemoteBlockSize_sp_basic256sha256;
- asym_encryptionAlgorithm->getLocalPlainTextBlockSize = NULL; // TODO: Write function
+ (size_t (*)(const void *))asym_getRemoteEncryptionKeyLength_sp_basic256sha256;
+ asym_encryptionAlgorithm->getRemoteBlockSize =
+ (size_t (*)(const void *))asym_getRemoteBlockSize_sp_basic256sha256;
asym_encryptionAlgorithm->getRemotePlainTextBlockSize =
- (size_t (*)(const UA_SecurityPolicy *, const void *))asym_getRemotePlainTextBlockSize_sp_basic256sha256;
+ (size_t (*)(const void *))asym_getRemotePlainTextBlockSize_sp_basic256sha256;
asymmetricModule->makeCertificateThumbprint = asym_makeThumbprint_sp_basic256sha256;
asymmetricModule->compareCertificateThumbprint =
@@ -61270,37 +69244,29 @@ UA_SecurityPolicy_Basic256Sha256(UA_SecurityPolicy *policy, const UA_ByteString
sym_signatureAlgorithm->uri =
UA_STRING("http://www.w3.org/2000/09/xmldsig#hmac-sha1\0");
sym_signatureAlgorithm->verify =
- (UA_StatusCode (*)(const UA_SecurityPolicy *, void *, const UA_ByteString *,
- const UA_ByteString *))sym_verify_sp_basic256sha256;
+ (UA_StatusCode (*)(void *, const UA_ByteString *, const UA_ByteString *))sym_verify_sp_basic256sha256;
sym_signatureAlgorithm->sign =
- (UA_StatusCode (*)(const UA_SecurityPolicy *, void *,
- const UA_ByteString *, UA_ByteString *))sym_sign_sp_basic256sha256;
+ (UA_StatusCode (*)(void *, const UA_ByteString *, UA_ByteString *))sym_sign_sp_basic256sha256;
sym_signatureAlgorithm->getLocalSignatureSize = sym_getSignatureSize_sp_basic256sha256;
sym_signatureAlgorithm->getRemoteSignatureSize = sym_getSignatureSize_sp_basic256sha256;
sym_signatureAlgorithm->getLocalKeyLength =
- (size_t (*)(const UA_SecurityPolicy *,
- const void *))sym_getSigningKeyLength_sp_basic256sha256;
+ (size_t (*)(const void *))sym_getSigningKeyLength_sp_basic256sha256;
sym_signatureAlgorithm->getRemoteKeyLength =
- (size_t (*)(const UA_SecurityPolicy *,
- const void *))sym_getSigningKeyLength_sp_basic256sha256;
+ (size_t (*)(const void *))sym_getSigningKeyLength_sp_basic256sha256;
UA_SecurityPolicyEncryptionAlgorithm *sym_encryptionAlgorithm =
&symmetricModule->cryptoModule.encryptionAlgorithm;
- sym_encryptionAlgorithm->uri = UA_STRING("http://www.w3.org/2001/04/xmlenc#aes128-cbc");
+ sym_encryptionAlgorithm->uri = UA_STRING("http://www.w3.org/2001/04/xmlenc#aes256-cbc");
sym_encryptionAlgorithm->encrypt =
- (UA_StatusCode(*)(const UA_SecurityPolicy *, void *, UA_ByteString *))sym_encrypt_sp_basic256sha256;
+ (UA_StatusCode(*)(void *, UA_ByteString *))sym_encrypt_sp_basic256sha256;
sym_encryptionAlgorithm->decrypt =
- (UA_StatusCode(*)(const UA_SecurityPolicy *, void *, UA_ByteString *))sym_decrypt_sp_basic256sha256;
+ (UA_StatusCode(*)(void *, UA_ByteString *))sym_decrypt_sp_basic256sha256;
sym_encryptionAlgorithm->getLocalKeyLength = sym_getEncryptionKeyLength_sp_basic256sha256;
sym_encryptionAlgorithm->getRemoteKeyLength = sym_getEncryptionKeyLength_sp_basic256sha256;
- sym_encryptionAlgorithm->getLocalBlockSize =
- (size_t (*)(const UA_SecurityPolicy *, const void *))sym_getEncryptionBlockSize_sp_basic256sha256;
sym_encryptionAlgorithm->getRemoteBlockSize =
- (size_t (*)(const UA_SecurityPolicy *, const void *))sym_getEncryptionBlockSize_sp_basic256sha256;
- sym_encryptionAlgorithm->getLocalPlainTextBlockSize =
- (size_t (*)(const UA_SecurityPolicy *, const void *))sym_getPlainTextBlockSize_sp_basic256sha256;
+ (size_t (*)(const void *))sym_getEncryptionBlockSize_sp_basic256sha256;
sym_encryptionAlgorithm->getRemotePlainTextBlockSize =
- (size_t (*)(const UA_SecurityPolicy *, const void *))sym_getPlainTextBlockSize_sp_basic256sha256;
+ (size_t (*)(const void *))sym_getPlainTextBlockSize_sp_basic256sha256;
symmetricModule->secureChannelNonceLength = 32;
// Use the same signature algorithm as the asymmetric component for certificate signing (see standard)
@@ -61340,3732 +69306,4409 @@ UA_SecurityPolicy_Basic256Sha256(UA_SecurityPolicy *policy, const UA_ByteString
#endif
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/plugins/securityPolicies/openssl/securitypolicy_openssl_common.h" ***********************************/
+/**** amalgamated original file "/plugins/crypto/mbedtls/ua_securitypolicy_aes128sha256rsaoaep.c" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
+ * Copyright 2018 (c) Mark Giraud, Fraunhofer IOSB
+ * Copyright 2018 (c) Daniel Feist, Precitec GmbH & Co. KG
+ * Copyright 2018 (c) HMS Industrial Networks AB (Author: Jonas Green)
* Copyright 2020 (c) Wind River Systems, Inc.
- * Copyright 2020 (c) basysKom GmbH
- *
*/
+#ifdef UA_ENABLE_ENCRYPTION_MBEDTLS
-#ifdef UA_ENABLE_ENCRYPTION_OPENSSL
-
-#include <openssl/x509.h>
-#include <openssl/evp.h>
-
-_UA_BEGIN_DECLS
-void saveDataToFile(const char *fileName, const UA_ByteString *str);
-void UA_Openssl_Init(void);
+#include <mbedtls/aes.h>
+#include <mbedtls/ctr_drbg.h>
+#include <mbedtls/entropy.h>
+#include <mbedtls/error.h>
+#include <mbedtls/md.h>
+#include <mbedtls/sha1.h>
+#include <mbedtls/sha256.h>
+#include <mbedtls/version.h>
+#include <mbedtls/x509_crt.h>
-UA_StatusCode
-UA_copyCertificate(UA_ByteString *dst, const UA_ByteString *src);
+/* Notes:
+ * mbedTLS' AES allows in-place encryption and decryption. So we don't have to
+ * allocate temp buffers.
+ * https://tls.mbed.org/discussions/generic/in-place-decryption-with-aes256-same-input-output-buffer
+ */
-UA_StatusCode
-UA_OpenSSL_RSA_PKCS1_V15_SHA256_Verify(const UA_ByteString *msg,
- X509 *publicKeyX509,
- const UA_ByteString *signature);
-UA_StatusCode
-UA_Openssl_X509_GetCertificateThumbprint(const UA_ByteString *certficate,
- UA_ByteString *pThumbprint,
- bool bThumbPrint);
-UA_StatusCode
-UA_Openssl_RSA_Oaep_Decrypt(UA_ByteString *data,
- EVP_PKEY *privateKey);
-UA_StatusCode
-UA_Openssl_RSA_OAEP_Encrypt(UA_ByteString *data, /* The data that is encrypted.
- The encrypted data will overwrite
- the data that was supplied. */
- size_t paddingSize, X509 *publicX509);
+#define UA_SECURITYPOLICY_AES128SHA256RSAOAEP_RSAPADDING_LEN 42
+#define UA_SHA1_LENGTH 20
+#define UA_SHA256_LENGTH 32
+#define UA_AES128SHA256RSAOAEP_SYM_SIGNING_KEY_LENGTH 32
+#define UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_KEY_LENGTH 16
+#define UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_ENCRYPTION_BLOCK_SIZE 16
+#define UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_PLAIN_TEXT_BLOCK_SIZE 16
+#define UA_SECURITYPOLICY_AES128SHA256RSAOAEP_MINASYMKEYLENGTH 256
+#define UA_SECURITYPOLICY_AES128SHA256RSAOAEP_MAXASYMKEYLENGTH 512
-UA_StatusCode
-UA_Openssl_Random_Key_PSHA256_Derive(const UA_ByteString *secret,
- const UA_ByteString *seed,
- UA_ByteString *out);
+typedef struct {
+ UA_ByteString localCertThumbprint;
-UA_StatusCode
-UA_Openssl_RSA_Public_GetKeyLength(X509 *publicKeyX509, UA_Int32 *keyLen);
+ mbedtls_ctr_drbg_context drbgContext;
+ mbedtls_entropy_context entropyContext;
+ mbedtls_md_context_t sha256MdContext;
+ mbedtls_pk_context localPrivateKey;
+} Aes128Sha256PsaOaep_PolicyContext;
-UA_StatusCode
-UA_Openssl_RSA_PKCS1_V15_SHA256_Sign(const UA_ByteString *data,
- EVP_PKEY *privateKey,
- UA_ByteString *outSignature);
+typedef struct {
+ Aes128Sha256PsaOaep_PolicyContext *policyContext;
-UA_StatusCode
-UA_OpenSSL_HMAC_SHA256_Verify(const UA_ByteString *message,
- const UA_ByteString *key,
- const UA_ByteString *signature);
+ UA_ByteString localSymSigningKey;
+ UA_ByteString localSymEncryptingKey;
+ UA_ByteString localSymIv;
-UA_StatusCode
-UA_OpenSSL_HMAC_SHA256_Sign(const UA_ByteString *message,
- const UA_ByteString *key,
- UA_ByteString *signature);
+ UA_ByteString remoteSymSigningKey;
+ UA_ByteString remoteSymEncryptingKey;
+ UA_ByteString remoteSymIv;
-UA_StatusCode
-UA_OpenSSL_AES_256_CBC_Decrypt(const UA_ByteString *iv,
- const UA_ByteString *key,
- UA_ByteString *data /* [in/out]*/);
+ mbedtls_x509_crt remoteCertificate;
+} Aes128Sha256PsaOaep_ChannelContext;
-UA_StatusCode
-UA_OpenSSL_AES_256_CBC_Encrypt(const UA_ByteString *iv,
- const UA_ByteString *key,
- UA_ByteString *data /* [in/out]*/);
+/********************/
+/* AsymmetricModule */
+/********************/
-UA_StatusCode
-UA_OpenSSL_X509_compare(const UA_ByteString *cert, const X509 *b);
+/* VERIFY AsymmetricSignatureAlgorithm_RSA-PKCS15-SHA2-256 */
+static UA_StatusCode
+asym_verify_sp_aes128sha256rsaoaep(Aes128Sha256PsaOaep_ChannelContext *cc,
+ const UA_ByteString *message,
+ const UA_ByteString *signature) {
+ if(message == NULL || signature == NULL || cc == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
-UA_StatusCode
-UA_Openssl_RSA_Private_GetKeyLength(EVP_PKEY *privateKey,
- UA_Int32 *keyLen) ;
+ unsigned char hash[UA_SHA256_LENGTH];
+#if MBEDTLS_VERSION_NUMBER >= 0x02070000 && MBEDTLS_VERSION_NUMBER < 0x03000000
+ // TODO check return status
+ mbedtls_sha256_ret(message->data, message->length, hash, 0);
+#else
+ mbedtls_sha256(message->data, message->length, hash, 0);
+#endif
-UA_StatusCode
-UA_OpenSSL_RSA_PKCS1_V15_SHA1_Verify(const UA_ByteString *msg,
- X509 *publicKeyX509,
- const UA_ByteString *signature);
+ /* Set the RSA settings */
+ mbedtls_rsa_context *rsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk);
+ mbedtls_rsa_set_padding(rsaContext, MBEDTLS_RSA_PKCS_V15, MBEDTLS_MD_SHA256);
-UA_StatusCode
-UA_Openssl_RSA_PKCS1_V15_SHA1_Sign(const UA_ByteString *message,
- EVP_PKEY *privateKey,
- UA_ByteString *outSignature);
-UA_StatusCode
-UA_Openssl_Random_Key_PSHA1_Derive(const UA_ByteString *secret,
- const UA_ByteString *seed,
- UA_ByteString *out);
-UA_StatusCode
-UA_OpenSSL_HMAC_SHA1_Verify(const UA_ByteString *message,
- const UA_ByteString *key,
- const UA_ByteString *signature);
+ /* For RSA keys, the default padding type is PKCS#1 v1.5 in mbedtls_pk_verify() */
+ /* Alternatively, use more specific function mbedtls_rsa_rsassa_pkcs1_v15_verify(), i.e. */
+ /* int mbedErr = mbedtls_rsa_rsassa_pkcs1_v15_verify(rsaContext, NULL, NULL,
+ MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA256,
+ UA_SHA256_LENGTH, hash,
+ signature->data); */
+ int mbedErr = mbedtls_pk_verify(&cc->remoteCertificate.pk,
+ MBEDTLS_MD_SHA256, hash, UA_SHA256_LENGTH,
+ signature->data, signature->length);
-UA_StatusCode
-UA_OpenSSL_HMAC_SHA1_Sign(const UA_ByteString *message,
- const UA_ByteString *key,
- UA_ByteString *signature);
+ if(mbedErr)
+ return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
+ return UA_STATUSCODE_GOOD;
+}
-UA_StatusCode
-UA_Openssl_RSA_PKCS1_V15_Decrypt(UA_ByteString *data,
- EVP_PKEY *privateKey);
+/* AsymmetricSignatureAlgorithm_RSA-PKCS15-SHA2-256 */
+static UA_StatusCode
+asym_sign_sp_aes128sha256rsaoaep(Aes128Sha256PsaOaep_ChannelContext *cc,
+ const UA_ByteString *message,
+ UA_ByteString *signature) {
+ if(message == NULL || signature == NULL || cc == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
-UA_StatusCode
-UA_Openssl_RSA_PKCS1_V15_Encrypt(UA_ByteString *data,
- size_t paddingSize,
- X509 *publicX509);
+ unsigned char hash[UA_SHA256_LENGTH];
+#if MBEDTLS_VERSION_NUMBER >= 0x02070000 && MBEDTLS_VERSION_NUMBER < 0x03000000
+ // TODO check return status
+ mbedtls_sha256_ret(message->data, message->length, hash, 0);
+#else
+ mbedtls_sha256(message->data, message->length, hash, 0);
+#endif
-UA_StatusCode
-UA_OpenSSL_AES_128_CBC_Decrypt(const UA_ByteString *iv,
- const UA_ByteString *key,
- UA_ByteString *data /* [in/out]*/);
+ Aes128Sha256PsaOaep_PolicyContext *pc = cc->policyContext;
+ mbedtls_rsa_context *rsaContext = mbedtls_pk_rsa(pc->localPrivateKey);
+ mbedtls_rsa_set_padding(rsaContext, MBEDTLS_RSA_PKCS_V15, MBEDTLS_MD_SHA256);
-UA_StatusCode
-UA_OpenSSL_AES_128_CBC_Encrypt(const UA_ByteString *iv,
- const UA_ByteString *key,
- UA_ByteString *data /* [in/out]*/);
+ size_t sigLen = 0;
-EVP_PKEY *
-UA_OpenSSL_LoadPrivateKey(const UA_ByteString *privateKey);
+ /* For RSA keys, the default padding type is PKCS#1 v1.5 in mbedtls_pk_sign */
+ /* Alternatively use more specific function mbedtls_rsa_rsassa_pkcs1_v15_sign() */
+ int mbedErr = mbedtls_pk_sign(&pc->localPrivateKey,
+ MBEDTLS_MD_SHA256, hash,
+ UA_SHA256_LENGTH, signature->data,
+#if MBEDTLS_VERSION_NUMBER >= 0x03000000
+ signature->length,
+#endif
+ &sigLen, mbedtls_ctr_drbg_random,
+ &pc->drbgContext);
+ if(mbedErr)
+ return UA_STATUSCODE_BADINTERNALERROR;
+ return UA_STATUSCODE_GOOD;
+}
-X509 *
-UA_OpenSSL_LoadCertificate(const UA_ByteString *certificate);
+static size_t
+asym_getLocalSignatureSize_sp_aes128sha256rsaoaep(const Aes128Sha256PsaOaep_ChannelContext *cc) {
+#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
+ return mbedtls_pk_rsa(cc->policyContext->localPrivateKey)->len;
+#else
+ if(cc == NULL)
+ return 0;
+ return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->policyContext->localPrivateKey));
+#endif
-X509 *
-UA_OpenSSL_LoadDerCertificate(const UA_ByteString *certificate);
+}
-X509 *
-UA_OpenSSL_LoadPemCertificate(const UA_ByteString *certificate);
+static size_t
+asym_getRemoteSignatureSize_sp_aes128sha256rsaoaep(const Aes128Sha256PsaOaep_ChannelContext *cc) {
+#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
+ return mbedtls_pk_rsa(cc->remoteCertificate.pk)->len;
+#else
+ if(cc == NULL)
+ return 0;
+ return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->remoteCertificate.pk));
+#endif
+}
-UA_StatusCode
-UA_OpenSSL_LoadLocalCertificate(const UA_ByteString *certificate, UA_ByteString *target);
+static size_t
+asym_getRemoteBlockSize_sp_aes128sha256rsaoaep(const Aes128Sha256PsaOaep_ChannelContext *cc) {
+#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
+ return mbedtls_pk_rsa(cc->remoteCertificate.pk)->len;
+#else
+ if(cc == NULL)
+ return 0;
+ return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->remoteCertificate.pk));
+#endif
+}
-_UA_END_DECLS
+static size_t
+asym_getRemotePlainTextBlockSize_sp_aes128sha256rsaoaep(const Aes128Sha256PsaOaep_ChannelContext *cc) {
+#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
+ mbedtls_rsa_context *const rsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk);
+ return rsaContext->len - UA_SECURITYPOLICY_AES128SHA256RSAOAEP_RSAPADDING_LEN;
+#else
+ if(cc == NULL)
+ return 0;
+ return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->remoteCertificate.pk)) -
+ UA_SECURITYPOLICY_AES128SHA256RSAOAEP_RSAPADDING_LEN;
+#endif
+}
-#endif /* UA_ENABLE_ENCRYPTION_OPENSSL */
+/* AsymmetricEncryptionAlgorithm_RSA-OAEP-SHA1 */
+static UA_StatusCode
+asym_encrypt_sp_aes128sha256rsaoaep(Aes128Sha256PsaOaep_ChannelContext *cc,
+ UA_ByteString *data) {
+ if(cc == NULL || data == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/plugins/securityPolicies/openssl/securitypolicy_openssl_common.c" ***********************************/
+ const size_t plainTextBlockSize = asym_getRemotePlainTextBlockSize_sp_aes128sha256rsaoaep(cc);
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- *
- * Copyright 2020 (c) Wind River Systems, Inc.
- * Copyright 2020 (c) basysKom GmbH
- */
+ mbedtls_rsa_context *remoteRsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk);
+ mbedtls_rsa_set_padding(remoteRsaContext, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA1);
-/*
-modification history
---------------------
-01feb20,lan written
-*/
+ return mbedtls_encrypt_rsaOaep(remoteRsaContext, &cc->policyContext->drbgContext,
+ data, plainTextBlockSize);
+}
+/* AsymmetricEncryptionAlgorithm_RSA-OAEP-SHA1 */
+static UA_StatusCode
+asym_decrypt_sp_aes128sha256rsaoaep(Aes128Sha256PsaOaep_ChannelContext *cc,
+ UA_ByteString *data) {
+ if(cc == NULL || data == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+ return mbedtls_decrypt_rsaOaep(&cc->policyContext->localPrivateKey,
+ &cc->policyContext->drbgContext, data);
+}
-#ifdef UA_ENABLE_ENCRYPTION_OPENSSL
+static size_t
+asym_getLocalEncryptionKeyLength_sp_aes128sha256rsaoaep(const Aes128Sha256PsaOaep_ChannelContext *cc) {
+ return mbedtls_pk_get_len(&cc->policyContext->localPrivateKey) * 8;
+}
-#include <openssl/rsa.h>
-#include <openssl/evp.h>
-#include <openssl/err.h>
-#include <openssl/sha.h>
-#include <openssl/x509.h>
-#include <openssl/hmac.h>
-#include <openssl/aes.h>
-#include <openssl/pem.h>
+static size_t
+asym_getRemoteEncryptionKeyLength_sp_aes128sha256rsaoaep(const Aes128Sha256PsaOaep_ChannelContext *cc) {
+ return mbedtls_pk_get_len(&cc->remoteCertificate.pk) * 8;
+}
+static UA_StatusCode
+asym_makeThumbprint_sp_aes128sha256rsaoaep(const UA_SecurityPolicy *securityPolicy,
+ const UA_ByteString *certificate,
+ UA_ByteString *thumbprint) {
+ if(securityPolicy == NULL || certificate == NULL || thumbprint == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+ return mbedtls_thumbprint_sha1(certificate, thumbprint);
+}
-#if OPENSSL_VERSION_NUMBER >= 0x1010000fL
-#define get_pkey_rsa(evp) EVP_PKEY_get0_RSA(evp)
-#else
-#define get_pkey_rsa(evp) ((evp)->pkey.rsa)
-#endif
+static UA_StatusCode
+asymmetricModule_compareCertificateThumbprint_sp_aes128sha256rsaoaep(const UA_SecurityPolicy *securityPolicy,
+ const UA_ByteString *certificateThumbprint) {
+ if(securityPolicy == NULL || certificateThumbprint == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
-#define SHA1_DIGEST_LENGTH 20 /* 160 bits */
+ Aes128Sha256PsaOaep_PolicyContext *pc = (Aes128Sha256PsaOaep_PolicyContext *)securityPolicy->policyContext;
+ if(!UA_ByteString_equal(certificateThumbprint, &pc->localCertThumbprint))
+ return UA_STATUSCODE_BADCERTIFICATEINVALID;
-/** P_SHA256 Context */
-typedef struct UA_Openssl_P_SHA256_Ctx_ {
- size_t seedLen;
- size_t secretLen;
- UA_Byte A[32]; /* 32 bytes of SHA256 output */
- /*
- char seed[seedLen];
- char secret[secretLen]; */
-} UA_Openssl_P_SHA256_Ctx;
+ return UA_STATUSCODE_GOOD;
+}
-#define UA_Openssl_P_SHA256_SEED(ctx) ((ctx)->A+32)
-#define UA_Openssl_P_SHA256_SECRET(ctx) ((ctx)->A+32+(ctx)->seedLen)
+/*******************/
+/* SymmetricModule */
+/*******************/
-/** P_SHA1 Context */
-typedef struct UA_Openssl_P_SHA1_Ctx_ {
- size_t seedLen;
- size_t secretLen;
- UA_Byte A[SHA1_DIGEST_LENGTH]; /* 20 bytes of SHA1 output */
- /*
- char seed[seedLen];
- char secret[secretLen]; */
-} UA_Openssl_P_SHA1_Ctx;
+static UA_StatusCode
+sym_verify_sp_aes128sha256rsaoaep(Aes128Sha256PsaOaep_ChannelContext *cc,
+ const UA_ByteString *message,
+ const UA_ByteString *signature) {
+ if(cc == NULL || message == NULL || signature == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
-#define UA_Openssl_P_SHA1_SEED(ctx) ((ctx)->A + SHA1_DIGEST_LENGTH)
-#define UA_Openssl_P_SHA1_SECRET(ctx) ((ctx)->A + SHA1_DIGEST_LENGTH +(ctx)->seedLen)
+ /* Compute MAC */
+ if(signature->length != UA_SHA256_LENGTH)
+ return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
+ Aes128Sha256PsaOaep_PolicyContext *pc = cc->policyContext;
+ unsigned char mac[UA_SHA256_LENGTH];
+ mbedtls_hmac(&pc->sha256MdContext, &cc->remoteSymSigningKey, message, mac);
-void
-UA_Openssl_Init (void) {
-/* VxWorks7 has initialized the openssl. */
-#ifndef __VXWORKS__
- static UA_Int16 bInit = 0;
- if (bInit == 1)
- return;
- OpenSSL_add_all_algorithms ();
- ERR_load_crypto_strings ();
- bInit = 1;
-#endif
+ /* Compare with Signature */
+ if(!UA_constantTimeEqual(signature->data, mac, UA_SHA256_LENGTH))
+ return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
+ return UA_STATUSCODE_GOOD;
}
-/* UA_copyCertificate - allocalte the buffer, copy the certificate and
- * add a NULL to the end
- */
-
-UA_StatusCode
-UA_copyCertificate (UA_ByteString * dst,
- const UA_ByteString * src) {
- UA_StatusCode retval = UA_ByteString_allocBuffer (dst, src->length + 1);
- if (retval != UA_STATUSCODE_GOOD)
- return retval;
- (void) memcpy (dst->data, src->data, src->length);
- dst->data[dst->length - 1] = '\0';
- dst->length--;
+static UA_StatusCode
+sym_sign_sp_aes128sha256rsaoaep(const Aes128Sha256PsaOaep_ChannelContext *cc,
+ const UA_ByteString *message,
+ UA_ByteString *signature) {
+ if(signature->length != UA_SHA256_LENGTH)
+ return UA_STATUSCODE_BADINTERNALERROR;
- return UA_STATUSCODE_GOOD;
+ mbedtls_hmac(&cc->policyContext->sha256MdContext, &cc->localSymSigningKey,
+ message, signature->data);
+ return UA_STATUSCODE_GOOD;
}
-static UA_StatusCode
-UA_OpenSSL_RSA_Public_Verify (const UA_ByteString * message,
- const EVP_MD * evpMd,
- X509 * publicKeyX509,
- UA_Int16 padding,
- const UA_ByteString * signature
- ) {
- EVP_MD_CTX * mdctx = NULL;
- int opensslRet;
- EVP_PKEY_CTX * evpKeyCtx;
- EVP_PKEY * evpPublicKey = NULL;
- UA_StatusCode ret;
+static size_t
+sym_getSignatureSize_sp_aes128sha256rsaoaep(const void *channelContext) {
+ return UA_SHA256_LENGTH;
+}
- mdctx = EVP_MD_CTX_create ();
- if (mdctx == NULL) {
- ret = UA_STATUSCODE_BADOUTOFMEMORY;
- goto errout;
- }
- evpPublicKey = X509_get_pubkey (publicKeyX509);
- if (evpPublicKey == NULL) {
- ret = UA_STATUSCODE_BADOUTOFMEMORY;
- goto errout;
- }
+static size_t
+sym_getSigningKeyLength_sp_aes128sha256rsaoaep(const void *channelContext) {
+ return UA_AES128SHA256RSAOAEP_SYM_SIGNING_KEY_LENGTH;
+}
- opensslRet = EVP_DigestVerifyInit (mdctx, &evpKeyCtx, evpMd, NULL,
- evpPublicKey);
- if (opensslRet != 1) {
- ret = UA_STATUSCODE_BADINTERNALERROR;
- goto errout;
- }
- EVP_PKEY_CTX_set_rsa_padding (evpKeyCtx, padding);
- opensslRet = EVP_DigestVerifyUpdate (mdctx, message->data, message->length);
- if (opensslRet != 1) {
- ret = UA_STATUSCODE_BADINTERNALERROR;
- goto errout;
- }
- opensslRet = EVP_DigestVerifyFinal(mdctx, signature->data, signature->length);
- if (opensslRet != 1) {
- ret = UA_STATUSCODE_BADINTERNALERROR;
- goto errout;
- }
+static size_t
+sym_getEncryptionKeyLength_sp_aes128sha256rsaoaep(const void *channelContext) {
+ return UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_KEY_LENGTH;
+}
- ret = UA_STATUSCODE_GOOD;
-errout:
- if (evpPublicKey != NULL) {
- EVP_PKEY_free (evpPublicKey);
- }
- if (mdctx != NULL) {
- EVP_MD_CTX_destroy (mdctx);
- }
- return ret;
+static size_t
+sym_getEncryptionBlockSize_sp_aes128sha256rsaoaep(const void *channelContext) {
+ return UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_ENCRYPTION_BLOCK_SIZE;
}
-UA_StatusCode
-UA_OpenSSL_RSA_PKCS1_V15_SHA256_Verify (const UA_ByteString * msg,
- X509 * publicKeyX509,
- const UA_ByteString * signature
- ) {
- return UA_OpenSSL_RSA_Public_Verify (msg, EVP_sha256(), publicKeyX509,
- NID_sha256, signature);
+static size_t
+sym_getPlainTextBlockSize_sp_aes128sha256rsaoaep(const void *channelContext) {
+ return UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_PLAIN_TEXT_BLOCK_SIZE;
}
-/* Get certificate thumbprint, and allocate the buffer.
- *
- */
+static UA_StatusCode
+sym_encrypt_sp_aes128sha256rsaoaep(const Aes128Sha256PsaOaep_ChannelContext *cc,
+ UA_ByteString *data) {
+ if(cc == NULL || data == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
-UA_StatusCode
-UA_Openssl_X509_GetCertificateThumbprint (const UA_ByteString * certficate,
- UA_ByteString * pThumbprint,
- bool bThumbPrint) {
- if (bThumbPrint) {
- pThumbprint->length = SHA_DIGEST_LENGTH;
- UA_StatusCode ret = UA_ByteString_allocBuffer (pThumbprint, pThumbprint->length);
- if (ret != UA_STATUSCODE_GOOD) {
- return ret;
- }
- }
- else {
- if (pThumbprint->length != SHA_DIGEST_LENGTH) {
- return UA_STATUSCODE_BADINTERNALERROR;
- }
- }
- X509 * x509Certificate = UA_OpenSSL_LoadCertificate(certficate);
+ if(cc->localSymIv.length != UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_ENCRYPTION_BLOCK_SIZE)
+ return UA_STATUSCODE_BADINTERNALERROR;
- if (x509Certificate == NULL) {
- if (bThumbPrint) {
- UA_ByteString_deleteMembers (pThumbprint);
- }
+ size_t plainTextBlockSize = UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_PLAIN_TEXT_BLOCK_SIZE;
+
+ if(data->length % plainTextBlockSize != 0)
return UA_STATUSCODE_BADINTERNALERROR;
- }
- if (X509_digest (x509Certificate, EVP_sha1(), pThumbprint->data, NULL)
- != 1) {
- if (bThumbPrint) {
- UA_ByteString_deleteMembers (pThumbprint);
- }
- return UA_STATUSCODE_BADINTERNALERROR;
- }
- X509_free(x509Certificate);
+ /* Keylength in bits */
+ unsigned int keylength = (unsigned int)(cc->localSymEncryptingKey.length * 8);
+ mbedtls_aes_context aesContext;
+ int mbedErr = mbedtls_aes_setkey_enc(&aesContext, cc->localSymEncryptingKey.data, keylength);
+ if(mbedErr)
+ return UA_STATUSCODE_BADINTERNALERROR;
- return UA_STATUSCODE_GOOD;
+ UA_ByteString ivCopy;
+ UA_StatusCode retval = UA_ByteString_copy(&cc->localSymIv, &ivCopy);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+
+ mbedErr = mbedtls_aes_crypt_cbc(&aesContext, MBEDTLS_AES_ENCRYPT, data->length,
+ ivCopy.data, data->data, data->data);
+ if(mbedErr)
+ retval = UA_STATUSCODE_BADINTERNALERROR;
+ UA_ByteString_clear(&ivCopy);
+ return retval;
}
static UA_StatusCode
-UA_Openssl_RSA_Private_Decrypt (UA_ByteString * data,
- EVP_PKEY * privateKey,
- UA_Int16 padding) {
- if (data == NULL || privateKey == NULL) {
- return UA_STATUSCODE_BADINVALIDARGUMENT;
- }
+sym_decrypt_sp_aes128sha256rsaoaep(const Aes128Sha256PsaOaep_ChannelContext *cc,
+ UA_ByteString *data) {
+ if(cc == NULL || data == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
- if (privateKey == NULL) {
- return UA_STATUSCODE_BADINVALIDARGUMENT;
- }
-
- UA_Int32 keySize = RSA_size(get_pkey_rsa(privateKey));
- size_t cipherOffset = 0;
- size_t outOffset = 0;
- unsigned char buf[2048];
- UA_Int32 decryptedBytes;
+ size_t encryptionBlockSize = UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_ENCRYPTION_BLOCK_SIZE;
- while (cipherOffset < data->length) {
- decryptedBytes = RSA_private_decrypt (keySize,
- data->data + cipherOffset, /* what to decrypt */
- buf, /* where to decrypt */
- get_pkey_rsa(privateKey), /* private key */
- padding
- );
- if (decryptedBytes < 0) {
- return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
- }
- memcpy(data->data + outOffset, buf, (size_t) decryptedBytes);
- cipherOffset += (size_t) keySize;
- outOffset += (size_t) decryptedBytes;
- }
- data->length = outOffset;
- return UA_STATUSCODE_GOOD;
-}
+ if(cc->remoteSymIv.length != encryptionBlockSize)
+ return UA_STATUSCODE_BADINTERNALERROR;
-UA_StatusCode
-UA_Openssl_RSA_Oaep_Decrypt (UA_ByteString * data,
- EVP_PKEY * privateKey) {
- return UA_Openssl_RSA_Private_Decrypt (data, privateKey,
- RSA_PKCS1_OAEP_PADDING);
+ if(data->length % encryptionBlockSize != 0)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ unsigned int keylength = (unsigned int)(cc->remoteSymEncryptingKey.length * 8);
+ mbedtls_aes_context aesContext;
+ int mbedErr = mbedtls_aes_setkey_dec(&aesContext, cc->remoteSymEncryptingKey.data, keylength);
+ if(mbedErr)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ UA_ByteString ivCopy;
+ UA_StatusCode retval = UA_ByteString_copy(&cc->remoteSymIv, &ivCopy);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+
+ mbedErr = mbedtls_aes_crypt_cbc(&aesContext, MBEDTLS_AES_DECRYPT, data->length,
+ ivCopy.data, data->data, data->data);
+ if(mbedErr)
+ retval = UA_STATUSCODE_BADINTERNALERROR;
+ UA_ByteString_clear(&ivCopy);
+ return retval;
}
static UA_StatusCode
-UA_Openssl_RSA_Public_Encrypt (const UA_ByteString * message,
- X509 * publicX509,
- UA_Int16 padding,
- size_t paddingSize,
- UA_ByteString * encrypted) {
- EVP_PKEY_CTX * ctx = NULL;
- EVP_PKEY * evpPublicKey = NULL;
- int opensslRet;
- UA_StatusCode ret;
+sym_generateKey_sp_aes128sha256rsaoaep(void *policyContext, const UA_ByteString *secret,
+ const UA_ByteString *seed, UA_ByteString *out) {
+ if(secret == NULL || seed == NULL || out == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+ Aes128Sha256PsaOaep_PolicyContext *pc = (Aes128Sha256PsaOaep_PolicyContext *)policyContext;
+ return mbedtls_generateKey(&pc->sha256MdContext, secret, seed, out);
+}
- evpPublicKey = X509_get_pubkey (publicX509);
- if (evpPublicKey == NULL) {
- ret = UA_STATUSCODE_BADOUTOFMEMORY;
- goto errout;
- }
- ctx = EVP_PKEY_CTX_new (evpPublicKey, NULL);
- if (ctx == NULL) {
- ret = UA_STATUSCODE_BADOUTOFMEMORY;
- goto errout;
- }
- opensslRet = EVP_PKEY_encrypt_init (ctx);
- if (opensslRet != 1) {
- ret = UA_STATUSCODE_BADINTERNALERROR;
- goto errout;
- }
- opensslRet = EVP_PKEY_CTX_set_rsa_padding (ctx, padding);
- if (opensslRet != 1) {
- ret = UA_STATUSCODE_BADINTERNALERROR;
- goto errout;
- }
-
- /* get the encrypted block size */
- size_t encryptedBlockSize;
- RSA * rsa = get_pkey_rsa (evpPublicKey);
- size_t keySize = (size_t) RSA_size (rsa);
- if (keySize == 0) {
- ret = UA_STATUSCODE_BADINTERNALERROR;
- goto errout;
- }
-
- switch (padding) {
- case RSA_PKCS1_OAEP_PADDING:
- case RSA_PKCS1_PADDING:
- if (keySize <= paddingSize) {
- ret = UA_STATUSCODE_BADINTERNALERROR;
- goto errout;
- }
- encryptedBlockSize = keySize - paddingSize;
- break;
- default:
- ret = UA_STATUSCODE_BADNOTSUPPORTED;
- goto errout;
- break;
- }
+static UA_StatusCode
+sym_generateNonce_sp_aes128sha256rsaoaep(void *policyContext, UA_ByteString *out) {
+ if(out == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+ Aes128Sha256PsaOaep_PolicyContext *pc =
+ (Aes128Sha256PsaOaep_PolicyContext *)policyContext;
+ int mbedErr = mbedtls_ctr_drbg_random(&pc->drbgContext, out->data, out->length);
+ if(mbedErr)
+ return UA_STATUSCODE_BADUNEXPECTEDERROR;
+ return UA_STATUSCODE_GOOD;
+}
- /* encrypt in reverse order so that [data] may alias [encrypted] */
+/*****************/
+/* ChannelModule */
+/*****************/
- size_t dataPos = message->length;
- size_t encryptedPos = ((dataPos - 1) / encryptedBlockSize + 1) * keySize;
- size_t bytesToEncrypt = (dataPos - 1) % encryptedBlockSize + 1;
- size_t encryptedTextLen = encryptedPos;
+/* Assumes that the certificate has been verified externally */
+static UA_StatusCode
+parseRemoteCertificate_sp_aes128sha256rsaoaep(Aes128Sha256PsaOaep_ChannelContext *cc,
+ const UA_ByteString *remoteCertificate) {
+ if(remoteCertificate == NULL || cc == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
- while (dataPos > 0) {
- size_t outlen = keySize;
- encryptedPos -= keySize;
- dataPos -= bytesToEncrypt;
- opensslRet = EVP_PKEY_encrypt (ctx, encrypted->data + encryptedPos, &outlen,
- message->data + dataPos, bytesToEncrypt);
-
- if (opensslRet != 1) {
- ret = UA_STATUSCODE_BADINTERNALERROR;
- goto errout;
- }
- bytesToEncrypt = encryptedBlockSize;
- }
- encrypted->length = encryptedTextLen;
+ /* Parse the certificate */
+ int mbedErr = mbedtls_x509_crt_parse(&cc->remoteCertificate, remoteCertificate->data,
+ remoteCertificate->length);
+ if(mbedErr)
+ return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
- ret = UA_STATUSCODE_GOOD;
-errout:
- if (evpPublicKey != NULL) {
- EVP_PKEY_free (evpPublicKey);
- }
- if (ctx != NULL) {
- EVP_PKEY_CTX_free (ctx);
- }
- return ret;
-}
+ /* Check the key length */
+#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
+ mbedtls_rsa_context *rsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk);
+ if(rsaContext->len < UA_SECURITYPOLICY_AES128SHA256RSAOAEP_MINASYMKEYLENGTH ||
+ rsaContext->len > UA_SECURITYPOLICY_AES128SHA256RSAOAEP_MAXASYMKEYLENGTH)
+#else
+ size_t keylen = mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->remoteCertificate.pk));
+ if(keylen < UA_SECURITYPOLICY_AES128SHA256RSAOAEP_MINASYMKEYLENGTH ||
+ keylen > UA_SECURITYPOLICY_AES128SHA256RSAOAEP_MAXASYMKEYLENGTH)
+#endif
+ return UA_STATUSCODE_BADCERTIFICATEUSENOTALLOWED;
-UA_StatusCode
-UA_Openssl_RSA_OAEP_Encrypt (UA_ByteString * data,
- size_t paddingSize,
- X509 * publicX509) {
- UA_ByteString message;
- UA_StatusCode ret;
-
- ret = UA_ByteString_copy (data, &message);
- if (ret != UA_STATUSCODE_GOOD) {
- return ret;
- }
- ret = UA_Openssl_RSA_Public_Encrypt (&message, publicX509,
- RSA_PKCS1_OAEP_PADDING,
- paddingSize,
- data);
- UA_ByteString_deleteMembers (&message);
- return ret;
+ return UA_STATUSCODE_GOOD;
}
-static UA_Openssl_P_SHA256_Ctx *
-P_SHA256_Ctx_Create (const UA_ByteString * secret,
- const UA_ByteString * seed) {
- size_t size = (UA_Int32)sizeof (UA_Openssl_P_SHA256_Ctx) + secret->length +
- seed->length;
- UA_Openssl_P_SHA256_Ctx * ctx = (UA_Openssl_P_SHA256_Ctx *) UA_malloc (size);
- if (ctx == NULL) {
- return NULL;
- }
- ctx->secretLen = secret->length;
- ctx->seedLen = seed->length;
- (void) memcpy (UA_Openssl_P_SHA256_SEED(ctx), seed->data, seed->length);
- (void) memcpy (UA_Openssl_P_SHA256_SECRET(ctx), secret->data, secret->length);
- /* A(0) = seed
- A(n) = HMAC_HASH(secret, A(n-1)) */
-
- if (HMAC (EVP_sha256(), secret->data, (int) secret->length, seed->data,
- seed->length, ctx->A, NULL) == NULL) {
- UA_free (ctx);
- return NULL;
- }
+static void
+channelContext_deleteContext_sp_aes128sha256rsaoaep(Aes128Sha256PsaOaep_ChannelContext *cc) {
+ UA_ByteString_clear(&cc->localSymSigningKey);
+ UA_ByteString_clear(&cc->localSymEncryptingKey);
+ UA_ByteString_clear(&cc->localSymIv);
- return ctx;
-}
+ UA_ByteString_clear(&cc->remoteSymSigningKey);
+ UA_ByteString_clear(&cc->remoteSymEncryptingKey);
+ UA_ByteString_clear(&cc->remoteSymIv);
-static UA_StatusCode
-P_SHA256_Hash_Generate (UA_Openssl_P_SHA256_Ctx * ctx,
- UA_Byte * pHas
- ) {
- /* Calculate P_SHA256(n) = HMAC_SHA256(secret, A(n)+seed) */
- if (HMAC (EVP_sha256(),UA_Openssl_P_SHA256_SECRET(ctx), (int) ctx->secretLen,
- ctx->A, sizeof (ctx->A) + ctx->seedLen, pHas, NULL) == NULL) {
- return UA_STATUSCODE_BADINTERNALERROR;
- }
+ mbedtls_x509_crt_free(&cc->remoteCertificate);
- /* Calculate A(n) = HMAC_SHA256(secret, A(n-1)) */
- if (HMAC (EVP_sha256(),UA_Openssl_P_SHA256_SECRET(ctx), (int) ctx->secretLen,
- ctx->A, sizeof (ctx->A), ctx->A, NULL) == NULL) {
- return UA_STATUSCODE_BADINTERNALERROR;
- }
- return UA_STATUSCODE_GOOD;
+ UA_free(cc);
}
-UA_StatusCode
-UA_Openssl_Random_Key_PSHA256_Derive (const UA_ByteString * secret,
- const UA_ByteString * seed,
- UA_ByteString * out) {
- size_t keyLen = out->length;
- size_t iter = keyLen/32 + ((keyLen%32)?1:0);
- size_t bufferLen = iter * 32;
- size_t i;
- UA_StatusCode st;
+static UA_StatusCode
+channelContext_newContext_sp_aes128sha256rsaoaep(const UA_SecurityPolicy *securityPolicy,
+ const UA_ByteString *remoteCertificate,
+ void **pp_contextData) {
+ if(securityPolicy == NULL || remoteCertificate == NULL || pp_contextData == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
- UA_Byte * pBuffer = (UA_Byte *) UA_malloc (bufferLen);
- if (pBuffer == NULL) {
+ /* Allocate the channel context */
+ *pp_contextData = UA_malloc(sizeof(Aes128Sha256PsaOaep_ChannelContext));
+ if(*pp_contextData == NULL)
return UA_STATUSCODE_BADOUTOFMEMORY;
- }
- UA_Openssl_P_SHA256_Ctx * ctx = P_SHA256_Ctx_Create (secret, seed);
- if (ctx == NULL) {
- UA_free (pBuffer);
- return UA_STATUSCODE_BADOUTOFMEMORY;
- }
+ Aes128Sha256PsaOaep_ChannelContext *cc = (Aes128Sha256PsaOaep_ChannelContext *)*pp_contextData;
- for (i = 0; i < iter; i++) {
- st = P_SHA256_Hash_Generate (ctx, pBuffer + (i * 32));
- if (st != UA_STATUSCODE_GOOD) {
- UA_free (pBuffer);
- UA_free (ctx);
- return st;
- }
- }
+ /* Initialize the channel context */
+ cc->policyContext = (Aes128Sha256PsaOaep_PolicyContext *)securityPolicy->policyContext;
- (void) memcpy (out->data, pBuffer, keyLen);
- UA_free (pBuffer);
- UA_free (ctx);
- return UA_STATUSCODE_GOOD;
-}
+ UA_ByteString_init(&cc->localSymSigningKey);
+ UA_ByteString_init(&cc->localSymEncryptingKey);
+ UA_ByteString_init(&cc->localSymIv);
-/* return the key bytes */
-UA_StatusCode
-UA_Openssl_RSA_Public_GetKeyLength (X509 * publicKeyX509,
- UA_Int32 * keyLen) {
- EVP_PKEY * evpKey = X509_get_pubkey (publicKeyX509);
- if (evpKey == NULL) {
- return UA_STATUSCODE_BADINTERNALERROR;
- }
- RSA * rsa = get_pkey_rsa (evpKey);
- *keyLen = RSA_size(rsa);
- EVP_PKEY_free (evpKey);
-
- return UA_STATUSCODE_GOOD;
-}
+ UA_ByteString_init(&cc->remoteSymSigningKey);
+ UA_ByteString_init(&cc->remoteSymEncryptingKey);
+ UA_ByteString_init(&cc->remoteSymIv);
-UA_StatusCode
-UA_Openssl_RSA_Private_GetKeyLength (EVP_PKEY * privateKey,
- UA_Int32 * keyLen) {
- if (privateKey == NULL) {
- return UA_STATUSCODE_BADINVALIDARGUMENT;
- }
- *keyLen = RSA_size(get_pkey_rsa(privateKey));
+ mbedtls_x509_crt_init(&cc->remoteCertificate);
- return UA_STATUSCODE_GOOD;
+ // TODO: this can be optimized so that we dont allocate memory before parsing the certificate
+ UA_StatusCode retval = parseRemoteCertificate_sp_aes128sha256rsaoaep(cc, remoteCertificate);
+ if(retval != UA_STATUSCODE_GOOD) {
+ channelContext_deleteContext_sp_aes128sha256rsaoaep(cc);
+ *pp_contextData = NULL;
+ }
+ return retval;
}
-static UA_StatusCode
-UA_Openssl_RSA_Private_Sign (const UA_ByteString * message,
- EVP_PKEY * privateKey,
- const EVP_MD * evpMd,
- UA_Int16 padding,
- UA_ByteString * outSignature) {
- EVP_MD_CTX * mdctx = NULL;
- int opensslRet;
- EVP_PKEY_CTX * evpKeyCtx;
- UA_StatusCode ret;
-
- mdctx = EVP_MD_CTX_create ();
- if (mdctx == NULL) {
- ret = UA_STATUSCODE_BADOUTOFMEMORY;
- goto errout;
- }
+static UA_StatusCode
+channelContext_setLocalSymEncryptingKey_sp_aes128sha256rsaoaep(Aes128Sha256PsaOaep_ChannelContext *cc,
+ const UA_ByteString *key) {
+ if(key == NULL || cc == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
- if (privateKey == NULL) {
- return UA_STATUSCODE_BADINVALIDARGUMENT;
- }
- opensslRet = EVP_DigestSignInit (mdctx, &evpKeyCtx, evpMd, NULL, privateKey);
- if (opensslRet != 1) {
- ret = UA_STATUSCODE_BADINTERNALERROR;
- goto errout;
- }
- EVP_PKEY_CTX_set_rsa_padding (evpKeyCtx, padding);
+ UA_ByteString_clear(&cc->localSymEncryptingKey);
+ return UA_ByteString_copy(key, &cc->localSymEncryptingKey);
+}
- opensslRet = EVP_DigestSignUpdate (mdctx, message->data, message->length);
- if (opensslRet != 1) {
- ret = UA_STATUSCODE_BADINTERNALERROR;
- goto errout;
- }
- opensslRet = EVP_DigestSignFinal (mdctx, outSignature->data, &outSignature->length);
- if (opensslRet != 1) {
- ret = UA_STATUSCODE_BADINTERNALERROR;
- goto errout;
- }
+static UA_StatusCode
+channelContext_setLocalSymSigningKey_sp_aes128sha256rsaoaep(Aes128Sha256PsaOaep_ChannelContext *cc,
+ const UA_ByteString *key) {
+ if(key == NULL || cc == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
- ret = UA_STATUSCODE_GOOD;
-errout:
- if (mdctx != NULL) {
- EVP_MD_CTX_destroy (mdctx);
- }
- return ret;
+ UA_ByteString_clear(&cc->localSymSigningKey);
+ return UA_ByteString_copy(key, &cc->localSymSigningKey);
}
-UA_StatusCode
-UA_Openssl_RSA_PKCS1_V15_SHA256_Sign (const UA_ByteString * message,
- EVP_PKEY * privateKey,
- UA_ByteString * outSignature) {
- return UA_Openssl_RSA_Private_Sign (message, privateKey, EVP_sha256(),
- NID_sha256, outSignature);
-}
-
-UA_StatusCode
-UA_OpenSSL_HMAC_SHA256_Verify (const UA_ByteString * message,
- const UA_ByteString * key,
- const UA_ByteString * signature
- ) {
- unsigned char buf[SHA256_DIGEST_LENGTH] = {0};
- UA_ByteString mac = {SHA256_DIGEST_LENGTH, buf};
- if (HMAC (EVP_sha256(), key->data, (int) key->length, message->data, message->length,
- mac.data, (unsigned int *) &mac.length) == NULL) {
- return UA_STATUSCODE_BADINTERNALERROR;
- }
- if (UA_ByteString_equal (signature, &mac)) {
- return UA_STATUSCODE_GOOD;
- }
- else {
+static UA_StatusCode
+channelContext_setLocalSymIv_sp_aes128sha256rsaoaep(Aes128Sha256PsaOaep_ChannelContext *cc,
+ const UA_ByteString *iv) {
+ if(iv == NULL || cc == NULL)
return UA_STATUSCODE_BADINTERNALERROR;
- }
+
+ UA_ByteString_clear(&cc->localSymIv);
+ return UA_ByteString_copy(iv, &cc->localSymIv);
}
-UA_StatusCode
-UA_OpenSSL_HMAC_SHA256_Sign (const UA_ByteString * message,
- const UA_ByteString * key,
- UA_ByteString * signature
- ) {
- if (HMAC (EVP_sha256(), key->data, (int) key->length, message->data,
- message->length,
- signature->data, (unsigned int *) &(signature->length)) == NULL) {
+static UA_StatusCode
+channelContext_setRemoteSymEncryptingKey_sp_aes128sha256rsaoaep(Aes128Sha256PsaOaep_ChannelContext *cc,
+ const UA_ByteString *key) {
+ if(key == NULL || cc == NULL)
return UA_STATUSCODE_BADINTERNALERROR;
- }
- return UA_STATUSCODE_GOOD;
-}
-static UA_StatusCode
-UA_OpenSSL_Decrypt (const UA_ByteString * iv,
- const UA_ByteString * key,
- const EVP_CIPHER * cipherAlg,
- UA_ByteString * data /* [in/out]*/) {
- UA_ByteString ivCopy = {0, NULL};
- UA_ByteString cipherTxt = {0, NULL};
- EVP_CIPHER_CTX * ctx = NULL;
- UA_StatusCode ret;
- int opensslRet;
- int outLen;
- int tmpLen;
+ UA_ByteString_clear(&cc->remoteSymEncryptingKey);
+ return UA_ByteString_copy(key, &cc->remoteSymEncryptingKey);
+}
- /* copy the IV because the AES_cbc_encrypt function overwrites it. */
+static UA_StatusCode
+channelContext_setRemoteSymSigningKey_sp_aes128sha256rsaoaep(Aes128Sha256PsaOaep_ChannelContext *cc,
+ const UA_ByteString *key) {
+ if(key == NULL || cc == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
- ret = UA_ByteString_copy (iv, &ivCopy);
- if (ret != UA_STATUSCODE_GOOD) {
- goto errout;
- }
+ UA_ByteString_clear(&cc->remoteSymSigningKey);
+ return UA_ByteString_copy(key, &cc->remoteSymSigningKey);
+}
- ret = UA_ByteString_copy (data, &cipherTxt);
- if (ret != UA_STATUSCODE_GOOD) {
- goto errout;
- }
-
- ctx = EVP_CIPHER_CTX_new ();
- if (ctx == NULL) {
- ret = UA_STATUSCODE_BADOUTOFMEMORY;
- goto errout;
- }
-
- /* call EVP_* to decrypt */
-
- opensslRet = EVP_DecryptInit_ex (ctx, cipherAlg, NULL, key->data, ivCopy.data);
- if (opensslRet != 1) {
- ret = UA_STATUSCODE_BADINTERNALERROR;
- goto errout;
- }
- /* EVP_DecryptFinal() will return an error code if padding is enabled
- * and the final block is not correctly formatted.
- */
- EVP_CIPHER_CTX_set_padding (ctx, 0);
- opensslRet = EVP_DecryptUpdate (ctx, data->data, &outLen,
- cipherTxt.data, (int) cipherTxt.length);
- if (opensslRet != 1) {
- ret = UA_STATUSCODE_BADINTERNALERROR;
- goto errout;
- }
- opensslRet = EVP_DecryptFinal_ex (ctx, data->data + outLen, &tmpLen);
- if (opensslRet != 1) {
- ret = UA_STATUSCODE_BADINTERNALERROR;
- goto errout;
- }
- outLen += tmpLen;
- data->length = (size_t) outLen;
- ret = UA_STATUSCODE_GOOD;
+static UA_StatusCode
+channelContext_setRemoteSymIv_sp_aes128sha256rsaoaep(Aes128Sha256PsaOaep_ChannelContext *cc,
+ const UA_ByteString *iv) {
+ if(iv == NULL || cc == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
-errout:
- UA_ByteString_deleteMembers (&ivCopy);
- UA_ByteString_deleteMembers (&cipherTxt);
- if (ctx != NULL) {
- EVP_CIPHER_CTX_free(ctx);
- }
- return ret;
+ UA_ByteString_clear(&cc->remoteSymIv);
+ return UA_ByteString_copy(iv, &cc->remoteSymIv);
}
static UA_StatusCode
-UA_OpenSSL_Encrypt (const UA_ByteString * iv,
- const UA_ByteString * key,
- const EVP_CIPHER * cipherAlg,
- UA_ByteString * data /* [in/out]*/
- ) {
+channelContext_compareCertificate_sp_aes128sha256rsaoaep(const Aes128Sha256PsaOaep_ChannelContext *cc,
+ const UA_ByteString *certificate) {
+ if(cc == NULL || certificate == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
- UA_ByteString ivCopy = {0, NULL};
- UA_ByteString plainTxt = {0, NULL};
- EVP_CIPHER_CTX * ctx = NULL;
- UA_StatusCode ret;
- int opensslRet;
- int outLen;
- int tmpLen;
+ mbedtls_x509_crt cert;
+ mbedtls_x509_crt_init(&cert);
+ int mbedErr = mbedtls_x509_crt_parse(&cert, certificate->data, certificate->length);
+ if(mbedErr)
+ return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
- /* copy the IV because the AES_cbc_encrypt function overwrites it. */
+ UA_StatusCode retval = UA_STATUSCODE_GOOD;
+ if(cert.raw.len != cc->remoteCertificate.raw.len ||
+ memcmp(cert.raw.p, cc->remoteCertificate.raw.p, cert.raw.len) != 0)
+ retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
- ret = UA_ByteString_copy (iv, &ivCopy);
- if (ret != UA_STATUSCODE_GOOD) {
- goto errout;
- }
+ mbedtls_x509_crt_free(&cert);
+ return retval;
+}
- ret = UA_ByteString_copy (data, &plainTxt);
- if (ret != UA_STATUSCODE_GOOD) {
- goto errout;
- }
-
- ctx = EVP_CIPHER_CTX_new ();
- if (ctx == NULL) {
- ret = UA_STATUSCODE_BADOUTOFMEMORY;
- goto errout;
- }
+static void
+clear_sp_aes128sha256rsaoaep(UA_SecurityPolicy *securityPolicy) {
+ if(securityPolicy == NULL)
+ return;
- /* call EVP_* to encrypt */
+ UA_ByteString_clear(&securityPolicy->localCertificate);
- opensslRet = EVP_EncryptInit_ex (ctx, cipherAlg, NULL, key->data, ivCopy.data);
- if (opensslRet != 1) {
- ret = UA_STATUSCODE_BADINTERNALERROR;
- goto errout;
- }
- opensslRet = EVP_EncryptUpdate (ctx, data->data, &outLen,
- plainTxt.data, (int) plainTxt.length);
- if (opensslRet != 1) {
- ret = UA_STATUSCODE_BADINTERNALERROR;
- goto errout;
- }
- /*
- * Buffer passed to EVP_EncryptFinal() must be after data just
- * encrypted to avoid overwriting it.
- */
- opensslRet = EVP_EncryptFinal_ex(ctx, data->data + outLen, &tmpLen);
- if (opensslRet != 1) {
- ret = UA_STATUSCODE_BADINTERNALERROR;
- goto errout;
- }
- outLen += tmpLen;
- data->length = (size_t) outLen;
- ret = UA_STATUSCODE_GOOD;
+ if(securityPolicy->policyContext == NULL)
+ return;
-errout:
- UA_ByteString_deleteMembers (&ivCopy);
- UA_ByteString_deleteMembers (&plainTxt);
- if (ctx != NULL) {
- EVP_CIPHER_CTX_free(ctx);
- }
- return ret;
-}
+ /* delete all allocated members in the context */
+ Aes128Sha256PsaOaep_PolicyContext *pc = (Aes128Sha256PsaOaep_PolicyContext *)
+ securityPolicy->policyContext;
-UA_StatusCode
-UA_OpenSSL_AES_256_CBC_Decrypt (const UA_ByteString * iv,
- const UA_ByteString * key,
- UA_ByteString * data /* [in/out]*/
- ) {
- return UA_OpenSSL_Decrypt (iv, key, EVP_aes_256_cbc (), data);
-}
+ mbedtls_ctr_drbg_free(&pc->drbgContext);
+ mbedtls_entropy_free(&pc->entropyContext);
+ mbedtls_pk_free(&pc->localPrivateKey);
+ mbedtls_md_free(&pc->sha256MdContext);
+ UA_ByteString_clear(&pc->localCertThumbprint);
-UA_StatusCode
-UA_OpenSSL_AES_256_CBC_Encrypt (const UA_ByteString * iv,
- const UA_ByteString * key,
- UA_ByteString * data /* [in/out]*/
- ) {
- return UA_OpenSSL_Encrypt (iv, key, EVP_aes_256_cbc (), data);
+ UA_LOG_DEBUG(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY,
+ "Deleted members of EndpointContext for sp_aes128sha256rsaoaep");
+
+ UA_free(pc);
+ securityPolicy->policyContext = NULL;
}
-UA_StatusCode
-UA_OpenSSL_X509_compare (const UA_ByteString * cert,
- const X509 * bcert) {
- X509 * acert = UA_OpenSSL_LoadCertificate(cert);
- if (acert == NULL) {
- return UA_STATUSCODE_BADCERTIFICATEINVALID;
- }
- int opensslRet = X509_cmp (acert, bcert);
- X509_free (acert);
+static UA_StatusCode
+updateCertificateAndPrivateKey_sp_aes128sha256rsaoaep(UA_SecurityPolicy *securityPolicy,
+ const UA_ByteString newCertificate,
+ const UA_ByteString newPrivateKey) {
+ if(securityPolicy == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
- if (opensslRet == 0)
- return UA_STATUSCODE_GOOD;
- return UA_STATUSCODE_UNCERTAINSUBNORMAL;
-}
+ if(securityPolicy->policyContext == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
-UA_StatusCode
-UA_OpenSSL_RSA_PKCS1_V15_SHA1_Verify (const UA_ByteString * msg,
- X509 * publicKeyX509,
- const UA_ByteString * signature) {
- return UA_OpenSSL_RSA_Public_Verify (msg, EVP_sha1(), publicKeyX509,
- NID_sha1, signature);
-}
+ Aes128Sha256PsaOaep_PolicyContext *pc =
+ (Aes128Sha256PsaOaep_PolicyContext *) securityPolicy->policyContext;
-UA_StatusCode
-UA_Openssl_RSA_PKCS1_V15_SHA1_Sign (const UA_ByteString * message,
- EVP_PKEY * privateKey,
- UA_ByteString * outSignature) {
- return UA_Openssl_RSA_Private_Sign (message, privateKey, EVP_sha1(),
- NID_sha1, outSignature);
-}
+ UA_ByteString_clear(&securityPolicy->localCertificate);
-static UA_Openssl_P_SHA1_Ctx *
-P_SHA1_Ctx_Create (const UA_ByteString * secret,
- const UA_ByteString * seed) {
- size_t size = (UA_Int32)sizeof (UA_Openssl_P_SHA1_Ctx) + secret->length +
- seed->length;
- UA_Openssl_P_SHA1_Ctx * ctx = (UA_Openssl_P_SHA1_Ctx *) UA_malloc (size);
- if (ctx == NULL) {
- return NULL;
- }
+ UA_StatusCode retval = UA_ByteString_allocBuffer(&securityPolicy->localCertificate,
+ newCertificate.length + 1);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+ memcpy(securityPolicy->localCertificate.data, newCertificate.data, newCertificate.length);
+ securityPolicy->localCertificate.data[newCertificate.length] = '\0';
+ securityPolicy->localCertificate.length--;
- ctx->secretLen = secret->length;
- ctx->seedLen = seed->length;
- (void) memcpy (UA_Openssl_P_SHA1_SEED(ctx), seed->data, seed->length);
- (void) memcpy (UA_Openssl_P_SHA1_SECRET(ctx), secret->data, secret->length);
- /* A(0) = seed
- A(n) = HMAC_HASH(secret, A(n-1)) */
-
- if (HMAC (EVP_sha1(), secret->data, (int) secret->length, seed->data,
- seed->length, ctx->A, NULL) == NULL) {
- UA_free (ctx);
- return NULL;
+ /* Set the new private key */
+ mbedtls_pk_free(&pc->localPrivateKey);
+ mbedtls_pk_init(&pc->localPrivateKey);
+#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
+ int mbedErr = mbedtls_pk_parse_key(&pc->localPrivateKey, newPrivateKey.data,
+ newPrivateKey.length, NULL, 0);
+#else
+ int mbedErr = mbedtls_pk_parse_key(&pc->localPrivateKey, newPrivateKey.data,
+ newPrivateKey.length, NULL, 0, mbedtls_entropy_func, &pc->drbgContext);
+#endif
+ if(mbedErr) {
+ retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
+ goto error;
}
- return ctx;
-}
+ retval = asym_makeThumbprint_sp_aes128sha256rsaoaep(securityPolicy,
+ &securityPolicy->localCertificate,
+ &pc->localCertThumbprint);
+ if(retval != UA_STATUSCODE_GOOD)
+ goto error;
-static UA_StatusCode
-P_SHA1_Hash_Generate (UA_Openssl_P_SHA1_Ctx * ctx,
- UA_Byte * pHas
- ) {
- /* Calculate P_SHA1(n) = HMAC_SHA1(secret, A(n)+seed) */
- if (HMAC (EVP_sha1 (), UA_Openssl_P_SHA1_SECRET(ctx), (int) ctx->secretLen,
- ctx->A, sizeof (ctx->A) + ctx->seedLen, pHas, NULL) == NULL) {
- return UA_STATUSCODE_BADINTERNALERROR;
- }
+ return retval;
- /* Calculate A(n) = HMAC_SHA1(secret, A(n-1)) */
- if (HMAC (EVP_sha1(), UA_Openssl_P_SHA1_SECRET(ctx), (int) ctx->secretLen,
- ctx->A, sizeof (ctx->A), ctx->A, NULL) == NULL) {
- return UA_STATUSCODE_BADINTERNALERROR;
- }
- return UA_STATUSCODE_GOOD;
+ error:
+ UA_LOG_ERROR(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY,
+ "Could not update certificate and private key");
+ if(securityPolicy->policyContext != NULL)
+ clear_sp_aes128sha256rsaoaep(securityPolicy);
+ return retval;
}
-UA_StatusCode
-UA_Openssl_Random_Key_PSHA1_Derive (const UA_ByteString * secret,
- const UA_ByteString * seed,
- UA_ByteString * out) {
- size_t keyLen = out->length;
- size_t iter = keyLen / SHA1_DIGEST_LENGTH + ((keyLen % SHA1_DIGEST_LENGTH)?1:0);
- size_t bufferLen = iter * SHA1_DIGEST_LENGTH;
- UA_Byte * pBuffer = (UA_Byte *) UA_malloc (bufferLen);
- if (pBuffer == NULL) {
- return UA_STATUSCODE_BADOUTOFMEMORY;
- }
+static UA_StatusCode
+policyContext_newContext_sp_aes128sha256rsaoaep(UA_SecurityPolicy *securityPolicy,
+ const UA_ByteString localPrivateKey) {
+ UA_StatusCode retval = UA_STATUSCODE_GOOD;
+ if(securityPolicy == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
- UA_Openssl_P_SHA1_Ctx * ctx = P_SHA1_Ctx_Create (secret, seed);
- if (ctx == NULL) {
- UA_free (pBuffer);
- return UA_STATUSCODE_BADOUTOFMEMORY;
+ if (localPrivateKey.length == 0) {
+ UA_LOG_ERROR(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY,
+ "Can not initialize security policy. Private key is empty.");
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
}
-
- size_t i;
- UA_StatusCode st;
- for (i = 0; i < iter; i++) {
- st = P_SHA1_Hash_Generate (ctx, pBuffer + (i * SHA1_DIGEST_LENGTH));
- if (st != UA_STATUSCODE_GOOD) {
- UA_free (pBuffer);
- UA_free (ctx);
- return st;
- }
+ Aes128Sha256PsaOaep_PolicyContext *pc = (Aes128Sha256PsaOaep_PolicyContext *)
+ UA_malloc(sizeof(Aes128Sha256PsaOaep_PolicyContext));
+ securityPolicy->policyContext = (void *)pc;
+ if(!pc) {
+ retval = UA_STATUSCODE_BADOUTOFMEMORY;
+ goto error;
}
- (void) memcpy (out->data, pBuffer, keyLen);
- UA_free (pBuffer);
- UA_free (ctx);
-
- return UA_STATUSCODE_GOOD;
-}
+ /* Initialize the PolicyContext */
+ memset(pc, 0, sizeof(Aes128Sha256PsaOaep_PolicyContext));
+ mbedtls_ctr_drbg_init(&pc->drbgContext);
+ mbedtls_entropy_init(&pc->entropyContext);
+ mbedtls_pk_init(&pc->localPrivateKey);
+ mbedtls_md_init(&pc->sha256MdContext);
-UA_StatusCode
-UA_OpenSSL_HMAC_SHA1_Verify (const UA_ByteString * message,
- const UA_ByteString * key,
- const UA_ByteString * signature
- ) {
- unsigned char buf[SHA1_DIGEST_LENGTH] = {0};
- UA_ByteString mac = {SHA1_DIGEST_LENGTH, buf};
+ /* Initialized the message digest */
+ const mbedtls_md_info_t *const mdInfo = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);
+ int mbedErr = mbedtls_md_setup(&pc->sha256MdContext, mdInfo, MBEDTLS_MD_SHA256);
+ if(mbedErr) {
+ retval = UA_STATUSCODE_BADOUTOFMEMORY;
+ goto error;
+ }
- if (HMAC (EVP_sha1(), key->data, (int) key->length, message->data, message->length,
- mac.data, (unsigned int *) &mac.length) == NULL) {
- return UA_STATUSCODE_BADINTERNALERROR;
+ mbedErr = mbedtls_entropy_self_test(0);
+
+ if(mbedErr) {
+ retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
+ goto error;
}
- if (UA_ByteString_equal (signature, &mac)) {
- return UA_STATUSCODE_GOOD;
+
+ /* Seed the RNG */
+ char *personalization = "open62541-drbg";
+ mbedErr = mbedtls_ctr_drbg_seed(&pc->drbgContext, mbedtls_entropy_func,
+ &pc->entropyContext,
+ (const unsigned char *)personalization, 14);
+ if(mbedErr) {
+ retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
+ goto error;
}
- else {
- return UA_STATUSCODE_BADINTERNALERROR;
- }
-}
-UA_StatusCode
-UA_OpenSSL_HMAC_SHA1_Sign (const UA_ByteString * message,
- const UA_ByteString * key,
- UA_ByteString * signature
- ) {
- if (HMAC (EVP_sha1(), key->data, (int) key->length, message->data,
- message->length,
- signature->data, (unsigned int *) &(signature->length)) == NULL) {
- return UA_STATUSCODE_BADINTERNALERROR;
+ /* Set the private key */
+ mbedErr = UA_mbedTLS_LoadPrivateKey(&localPrivateKey, &pc->localPrivateKey, &pc->entropyContext);
+ if(mbedErr) {
+ retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
+ goto error;
}
+
+ /* Set the local certificate thumbprint */
+ retval = UA_ByteString_allocBuffer(&pc->localCertThumbprint, UA_SHA1_LENGTH);
+ if(retval != UA_STATUSCODE_GOOD)
+ goto error;
+ retval = asym_makeThumbprint_sp_aes128sha256rsaoaep(securityPolicy,
+ &securityPolicy->localCertificate,
+ &pc->localCertThumbprint);
+ if(retval != UA_STATUSCODE_GOOD)
+ goto error;
+
return UA_STATUSCODE_GOOD;
-}
-UA_StatusCode
-UA_Openssl_RSA_PKCS1_V15_Decrypt (UA_ByteString * data,
- EVP_PKEY * privateKey) {
- return UA_Openssl_RSA_Private_Decrypt (data, privateKey,
- RSA_PKCS1_PADDING);
+error:
+ UA_LOG_ERROR(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY,
+ "Could not create securityContext: %s", UA_StatusCode_name(retval));
+ if(securityPolicy->policyContext != NULL)
+ clear_sp_aes128sha256rsaoaep(securityPolicy);
+ return retval;
}
UA_StatusCode
-UA_Openssl_RSA_PKCS1_V15_Encrypt (UA_ByteString * data,
- size_t paddingSize,
- X509 * publicX509) {
- UA_ByteString message;
- UA_StatusCode ret;
-
- ret = UA_ByteString_copy (data, &message);
- if (ret != UA_STATUSCODE_GOOD) {
- return ret;
- }
- ret = UA_Openssl_RSA_Public_Encrypt (&message, publicX509,
- RSA_PKCS1_PADDING,
- paddingSize,
- data);
- UA_ByteString_deleteMembers (&message);
- return ret;
-}
+UA_SecurityPolicy_Aes128Sha256RsaOaep(UA_SecurityPolicy *policy, const UA_ByteString localCertificate,
+ const UA_ByteString localPrivateKey, const UA_Logger *logger) {
+ memset(policy, 0, sizeof(UA_SecurityPolicy));
+ policy->logger = logger;
-UA_StatusCode
-UA_OpenSSL_AES_128_CBC_Decrypt (const UA_ByteString * iv,
- const UA_ByteString * key,
- UA_ByteString * data /* [in/out]*/
- ) {
- return UA_OpenSSL_Decrypt (iv, key, EVP_aes_128_cbc (), data);
-}
+ policy->policyUri = UA_STRING("http://opcfoundation.org/UA/SecurityPolicy#Aes128_Sha256_RsaOaep");
-UA_StatusCode
-UA_OpenSSL_AES_128_CBC_Encrypt (const UA_ByteString * iv,
- const UA_ByteString * key,
- UA_ByteString * data /* [in/out]*/
- ) {
- return UA_OpenSSL_Encrypt (iv, key, EVP_aes_128_cbc (), data);
-}
+ UA_SecurityPolicyAsymmetricModule *const asymmetricModule = &policy->asymmetricModule;
+ UA_SecurityPolicySymmetricModule *const symmetricModule = &policy->symmetricModule;
+ UA_SecurityPolicyChannelModule *const channelModule = &policy->channelModule;
-EVP_PKEY *
-UA_OpenSSL_LoadPrivateKey(const UA_ByteString *privateKey) {
- const unsigned char * pkData = privateKey->data;
- long len = (long) privateKey->length;
+ UA_StatusCode retval = UA_mbedTLS_LoadLocalCertificate(&localCertificate, &policy->localCertificate);
- EVP_PKEY *result = NULL;
+ if (retval != UA_STATUSCODE_GOOD)
+ return retval;
- if (len > 1 && pkData[0] == 0x30 && pkData[1] == 0x82) { // Magic number for DER encoded keys
- result = d2i_PrivateKey(EVP_PKEY_RSA, NULL,
- &pkData, len);
- } else {
- BIO *bio = NULL;
-#if OPENSSL_VERSION_NUMBER < 0x1000207fL
- bio = BIO_new_mem_buf((void *) privateKey->data, (int) privateKey->length);
-#else
- bio = BIO_new_mem_buf((const void *) privateKey->data, (int) privateKey->length);
-#endif
- result = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
- BIO_free(bio);
- }
+ /* AsymmetricModule */
+ UA_SecurityPolicySignatureAlgorithm *asym_signatureAlgorithm =
+ &asymmetricModule->cryptoModule.signatureAlgorithm;
+ asym_signatureAlgorithm->uri =
+ UA_STRING("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256\0");
+ asym_signatureAlgorithm->verify =
+ (UA_StatusCode (*)(void *, const UA_ByteString *, const UA_ByteString *))asym_verify_sp_aes128sha256rsaoaep;
+ asym_signatureAlgorithm->sign =
+ (UA_StatusCode (*)(void *, const UA_ByteString *, UA_ByteString *))asym_sign_sp_aes128sha256rsaoaep;
+ asym_signatureAlgorithm->getLocalSignatureSize =
+ (size_t (*)(const void *))asym_getLocalSignatureSize_sp_aes128sha256rsaoaep;
+ asym_signatureAlgorithm->getRemoteSignatureSize =
+ (size_t (*)(const void *))asym_getRemoteSignatureSize_sp_aes128sha256rsaoaep;
+ asym_signatureAlgorithm->getLocalKeyLength = NULL; // TODO: Write function
+ asym_signatureAlgorithm->getRemoteKeyLength = NULL; // TODO: Write function
- return result;
-}
+ UA_SecurityPolicyEncryptionAlgorithm *asym_encryptionAlgorithm =
+ &asymmetricModule->cryptoModule.encryptionAlgorithm;
+ asym_encryptionAlgorithm->uri = UA_STRING("http://www.w3.org/2001/04/xmlenc#rsa-oaep\0");
+ asym_encryptionAlgorithm->encrypt =
+ (UA_StatusCode(*)(void *, UA_ByteString *))asym_encrypt_sp_aes128sha256rsaoaep;
+ asym_encryptionAlgorithm->decrypt =
+ (UA_StatusCode(*)(void *, UA_ByteString *)) asym_decrypt_sp_aes128sha256rsaoaep;
+ asym_encryptionAlgorithm->getLocalKeyLength =
+ (size_t (*)(const void *))asym_getLocalEncryptionKeyLength_sp_aes128sha256rsaoaep;
+ asym_encryptionAlgorithm->getRemoteKeyLength =
+ (size_t (*)(const void *))asym_getRemoteEncryptionKeyLength_sp_aes128sha256rsaoaep;
+ asym_encryptionAlgorithm->getRemoteBlockSize = (size_t (*)(const void *))asym_getRemoteBlockSize_sp_aes128sha256rsaoaep;
+ asym_encryptionAlgorithm->getRemotePlainTextBlockSize =
+ (size_t (*)(const void *))asym_getRemotePlainTextBlockSize_sp_aes128sha256rsaoaep;
-X509 *
-UA_OpenSSL_LoadCertificate(const UA_ByteString *certificate) {
- X509 * result = NULL;
- const unsigned char *pData = certificate->data;
+ asymmetricModule->makeCertificateThumbprint = asym_makeThumbprint_sp_aes128sha256rsaoaep;
+ asymmetricModule->compareCertificateThumbprint =
+ asymmetricModule_compareCertificateThumbprint_sp_aes128sha256rsaoaep;
- if (certificate->length > 1 && pData[0] == 0x30 && pData[1] == 0x82) { // Magic number for DER encoded files
- result = UA_OpenSSL_LoadDerCertificate(certificate);
- } else {
- result = UA_OpenSSL_LoadPemCertificate(certificate);
- }
+ /* SymmetricModule */
+ symmetricModule->generateKey = sym_generateKey_sp_aes128sha256rsaoaep;
+ symmetricModule->generateNonce = sym_generateNonce_sp_aes128sha256rsaoaep;
- return result;
-}
+ UA_SecurityPolicySignatureAlgorithm *sym_signatureAlgorithm =
+ &symmetricModule->cryptoModule.signatureAlgorithm;
+ sym_signatureAlgorithm->uri =
+ UA_STRING("http://www.w3.org/2000/09/xmldsig#hmac-sha1\0");
+ sym_signatureAlgorithm->verify =
+ (UA_StatusCode (*)(void *, const UA_ByteString *, const UA_ByteString *))sym_verify_sp_aes128sha256rsaoaep;
+ sym_signatureAlgorithm->sign =
+ (UA_StatusCode (*)(void *, const UA_ByteString *, UA_ByteString *))sym_sign_sp_aes128sha256rsaoaep;
+ sym_signatureAlgorithm->getLocalSignatureSize = sym_getSignatureSize_sp_aes128sha256rsaoaep;
+ sym_signatureAlgorithm->getRemoteSignatureSize = sym_getSignatureSize_sp_aes128sha256rsaoaep;
+ sym_signatureAlgorithm->getLocalKeyLength =
+ (size_t (*)(const void *))sym_getSigningKeyLength_sp_aes128sha256rsaoaep;
+ sym_signatureAlgorithm->getRemoteKeyLength =
+ (size_t (*)(const void *))sym_getSigningKeyLength_sp_aes128sha256rsaoaep;
-X509 *
-UA_OpenSSL_LoadDerCertificate(const UA_ByteString *certificate) {
- const unsigned char *pData = certificate->data;
- return d2i_X509(NULL, &pData, (long) certificate->length);
-}
+ UA_SecurityPolicyEncryptionAlgorithm *sym_encryptionAlgorithm =
+ &symmetricModule->cryptoModule.encryptionAlgorithm;
+ sym_encryptionAlgorithm->uri = UA_STRING("http://www.w3.org/2001/04/xmlenc#aes128-cbc");
+ sym_encryptionAlgorithm->encrypt =
+ (UA_StatusCode(*)(void *, UA_ByteString *))sym_encrypt_sp_aes128sha256rsaoaep;
+ sym_encryptionAlgorithm->decrypt =
+ (UA_StatusCode(*)(void *, UA_ByteString *))sym_decrypt_sp_aes128sha256rsaoaep;
+ sym_encryptionAlgorithm->getLocalKeyLength = sym_getEncryptionKeyLength_sp_aes128sha256rsaoaep;
+ sym_encryptionAlgorithm->getRemoteKeyLength = sym_getEncryptionKeyLength_sp_aes128sha256rsaoaep;
+ sym_encryptionAlgorithm->getRemoteBlockSize =
+ (size_t (*)(const void *))sym_getEncryptionBlockSize_sp_aes128sha256rsaoaep;
+ sym_encryptionAlgorithm->getRemotePlainTextBlockSize =
+ (size_t (*)(const void *))sym_getPlainTextBlockSize_sp_aes128sha256rsaoaep;
+ symmetricModule->secureChannelNonceLength = 32;
-X509 *
-UA_OpenSSL_LoadPemCertificate(const UA_ByteString *certificate) {
- X509 * result = NULL;
+ // Use the same signature algorithm as the asymmetric component for certificate signing (see standard)
+ policy->certificateSigningAlgorithm = policy->asymmetricModule.cryptoModule.signatureAlgorithm;
- BIO* bio = NULL;
-#if OPENSSL_VERSION_NUMBER < 0x1000207fL
- bio = BIO_new_mem_buf((void *) certificate->data, (int) certificate->length);
-#else
- bio = BIO_new_mem_buf((const void *) certificate->data, (int) certificate->length);
-#endif
- result = PEM_read_bio_X509(bio, NULL, NULL, NULL);
- BIO_free(bio);
+ /* ChannelModule */
+ channelModule->newContext = channelContext_newContext_sp_aes128sha256rsaoaep;
+ channelModule->deleteContext = (void (*)(void *))
+ channelContext_deleteContext_sp_aes128sha256rsaoaep;
- return result;
-}
+ channelModule->setLocalSymEncryptingKey = (UA_StatusCode (*)(void *, const UA_ByteString *))
+ channelContext_setLocalSymEncryptingKey_sp_aes128sha256rsaoaep;
+ channelModule->setLocalSymSigningKey = (UA_StatusCode (*)(void *, const UA_ByteString *))
+ channelContext_setLocalSymSigningKey_sp_aes128sha256rsaoaep;
+ channelModule->setLocalSymIv = (UA_StatusCode (*)(void *, const UA_ByteString *))
+ channelContext_setLocalSymIv_sp_aes128sha256rsaoaep;
-UA_StatusCode
-UA_OpenSSL_LoadLocalCertificate(const UA_ByteString *certificate, UA_ByteString *target) {
- X509 *cert = UA_OpenSSL_LoadCertificate(certificate);
+ channelModule->setRemoteSymEncryptingKey = (UA_StatusCode (*)(void *, const UA_ByteString *))
+ channelContext_setRemoteSymEncryptingKey_sp_aes128sha256rsaoaep;
+ channelModule->setRemoteSymSigningKey = (UA_StatusCode (*)(void *, const UA_ByteString *))
+ channelContext_setRemoteSymSigningKey_sp_aes128sha256rsaoaep;
+ channelModule->setRemoteSymIv = (UA_StatusCode (*)(void *, const UA_ByteString *))
+ channelContext_setRemoteSymIv_sp_aes128sha256rsaoaep;
- if (!cert)
- return UA_STATUSCODE_BADINVALIDARGUMENT;
+ channelModule->compareCertificate = (UA_StatusCode (*)(const void *, const UA_ByteString *))
+ channelContext_compareCertificate_sp_aes128sha256rsaoaep;
- unsigned char *derData = NULL;
- int length = i2d_X509(cert, &derData);
- X509_free(cert);
+ policy->updateCertificateAndPrivateKey = updateCertificateAndPrivateKey_sp_aes128sha256rsaoaep;
+ policy->clear = clear_sp_aes128sha256rsaoaep;
- if (length > 0) {
- UA_ByteString temp;
- temp.length = (size_t) length;
- temp.data = derData;
- UA_ByteString_copy(&temp, target);
- OPENSSL_free(derData);
- return UA_STATUSCODE_GOOD;
- }
+ UA_StatusCode res = policyContext_newContext_sp_aes128sha256rsaoaep(policy, localPrivateKey);
+ if(res != UA_STATUSCODE_GOOD)
+ clear_sp_aes128sha256rsaoaep(policy);
- return UA_STATUSCODE_BADINVALIDARGUMENT;
+ return res;
}
-
#endif
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/plugins/securityPolicies/openssl/ua_openssl_basic128rsa15.c" ***********************************/
+/**** amalgamated original file "/plugins/crypto/mbedtls/ua_pki_mbedtls.c" ****/
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
+ * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
*
- * Copyright 2020 (c) Wind River Systems, Inc.
- * Copyright 2020 (c) basysKom GmbH
+ * Copyright 2018 (c) Mark Giraud, Fraunhofer IOSB
+ * Copyright 2019 (c) Kalycito Infotech Private Limited
+ * Copyright 2019 (c) Julius Pfrommer, Fraunhofer IOSB
*/
-/*
-modification history
---------------------
-18mar20,lan written
-*/
-
-#ifdef UA_ENABLE_ENCRYPTION_OPENSSL
+#ifdef UA_ENABLE_ENCRYPTION_MBEDTLS
+#include <mbedtls/x509.h>
+#include <mbedtls/x509_crt.h>
+#include <mbedtls/error.h>
+#include <mbedtls/version.h>
-#include <openssl/x509.h>
-#include <openssl/rand.h>
-#include <openssl/evp.h>
+#define REMOTECERTIFICATETRUSTED 1
+#define ISSUERKNOWN 2
+#define DUALPARENT 3
+#define PARENTFOUND 4
-#define UA_SHA1_LENGTH 20
-#define UA_SECURITYPOLICY_BASIC128RSA15_RSAPADDING_LEN 11
-#define UA_SECURITYPOLICY_BASIC128RSA15_SYM_ENCRYPTION_KEY_LENGTH 16
-#define UA_SECURITYPOLICY_BASIC128RSA15_SYM_ENCRYPTION_BLOCK_SIZE 16
-#define UA_SECURITYPOLICY_BASIC128RSA15_SYM_PLAIN_TEXT_BLOCK_SIZE 16
-#define UA_SECURITYPOLICY_BASIC128RSA15_SYM_SIGNING_KEY_LENGTH 16
-#define UA_SHA1_LENGTH 20
+/* Find binary substring. Taken and adjusted from
+ * http://tungchingkai.blogspot.com/2011/07/binary-strstr.html */
-typedef struct {
- EVP_PKEY * localPrivateKey;
- UA_ByteString localCertThumbprint;
- const UA_Logger * logger;
-} Policy_Context_Basic128Rsa15;
+static const unsigned char *
+bstrchr(const unsigned char *s, const unsigned char ch, size_t l) {
+ /* find first occurrence of c in char s[] for length l*/
+ for(; l > 0; ++s, --l) {
+ if(*s == ch)
+ return s;
+ }
+ return NULL;
+}
-typedef struct {
- UA_ByteString localSymSigningKey;
- UA_ByteString localSymEncryptingKey;
- UA_ByteString localSymIv;
- UA_ByteString remoteSymSigningKey;
- UA_ByteString remoteSymEncryptingKey;
- UA_ByteString remoteSymIv;
+static const unsigned char *
+UA_Bstrstr(const unsigned char *s1, size_t l1, const unsigned char *s2, size_t l2) {
+ /* find first occurrence of s2[] in s1[] for length l1*/
+ const unsigned char *ss1 = s1;
+ const unsigned char *ss2 = s2;
+ /* handle special case */
+ if(l1 == 0)
+ return (NULL);
+ if(l2 == 0)
+ return s1;
- Policy_Context_Basic128Rsa15 * policyContext;
- UA_ByteString remoteCertificate;
- X509 * remoteCertificateX509;
-} Channel_Context_Basic128Rsa15;
+ /* match prefix */
+ for (; (s1 = bstrchr(s1, *s2, (uintptr_t)ss1-(uintptr_t)s1+(uintptr_t)l1)) != NULL &&
+ (uintptr_t)ss1-(uintptr_t)s1+(uintptr_t)l1 != 0; ++s1) {
-static UA_StatusCode
-UA_Policy_Basic128Rsa15_New_Context (UA_SecurityPolicy * securityPolicy,
- const UA_ByteString localPrivateKey,
- const UA_Logger * logger) {
- Policy_Context_Basic128Rsa15 * context = (Policy_Context_Basic128Rsa15 *)
- UA_malloc (sizeof (Policy_Context_Basic128Rsa15));
- if (context == NULL) {
- return UA_STATUSCODE_BADOUTOFMEMORY;
+ /* match rest of prefix */
+ const unsigned char *sc1, *sc2;
+ for (sc1 = s1, sc2 = s2; ;)
+ if (++sc2 >= ss2+l2)
+ return s1;
+ else if (*++sc1 != *sc2)
+ break;
}
+ return NULL;
+}
- context->localPrivateKey = UA_OpenSSL_LoadPrivateKey(&localPrivateKey);
+// mbedTLS expects PEM data to be null terminated
+// The data length parameter must include the null terminator
+static UA_ByteString copyDataFormatAware(const UA_ByteString *data)
+{
+ UA_ByteString result;
+ UA_ByteString_init(&result);
- if (!context->localPrivateKey) {
- UA_free(context);
- return UA_STATUSCODE_BADINVALIDARGUMENT;
- }
+ if (!data->length)
+ return result;
- UA_StatusCode retval = UA_Openssl_X509_GetCertificateThumbprint (
- &securityPolicy->localCertificate,
- &context->localCertThumbprint, true
- );
- if (retval != UA_STATUSCODE_GOOD) {
- EVP_PKEY_free(context->localPrivateKey);
- UA_free (context);
- return retval;
+ if (data->length && data->data[0] == '-') {
+ UA_ByteString_allocBuffer(&result, data->length + 1);
+ memcpy(result.data, data->data, data->length);
+ result.data[data->length] = '\0';
+ } else {
+ UA_ByteString_copy(data, &result);
}
- context->logger = logger;
- securityPolicy->policyContext = context;
-
- return UA_STATUSCODE_GOOD;
-}
+ return result;
+}
-static void
-UA_Policy_Basic128Rsa15_Clear_Context (UA_SecurityPolicy *policy) {
- if (policy == NULL) {
- return;
- }
- UA_ByteString_deleteMembers(&policy->localCertificate);
+typedef struct {
+ /* If the folders are defined, we use them to reload the certificates during
+ * runtime */
+ UA_String trustListFolder;
+ UA_String issuerListFolder;
+ UA_String revocationListFolder;
- Policy_Context_Basic128Rsa15 * ctx = (Policy_Context_Basic128Rsa15 *) policy->policyContext;
- if (ctx == NULL) {
- return;
- }
+ mbedtls_x509_crt certificateTrustList;
+ mbedtls_x509_crt certificateIssuerList;
+ mbedtls_x509_crl certificateRevocationList;
+} CertInfo;
- /* delete all allocated members in the context */
+#ifdef __linux__ /* Linux only so far */
- EVP_PKEY_free(ctx->localPrivateKey);
- UA_ByteString_deleteMembers (&ctx->localCertThumbprint);
- UA_free (ctx);
+#include <dirent.h>
+#include <limits.h>
- return;
-}
+static UA_StatusCode
+fileNamesFromFolder(const UA_String *folder, size_t *pathsSize, UA_String **paths) {
+ char buf[PATH_MAX + 1];
+ if(folder->length > PATH_MAX)
+ return UA_STATUSCODE_BADINTERNALERROR;
-/* create the channel context */
+ memcpy(buf, folder->data, folder->length);
+ buf[folder->length] = 0;
+
+ DIR *dir = opendir(buf);
+ if(!dir)
+ return UA_STATUSCODE_BADINTERNALERROR;
-static UA_StatusCode
-UA_ChannelModule_Basic128Rsa15_New_Context (const UA_SecurityPolicy * securityPolicy,
- const UA_ByteString * remoteCertificate,
- void ** channelContext) {
- if (securityPolicy == NULL || remoteCertificate == NULL ||
- channelContext == NULL) {
- return UA_STATUSCODE_BADINTERNALERROR;
- }
- Channel_Context_Basic128Rsa15 * context = (Channel_Context_Basic128Rsa15 *)
- UA_malloc (sizeof (Channel_Context_Basic128Rsa15));
- if (context == NULL) {
+ *paths = (UA_String*)UA_Array_new(256, &UA_TYPES[UA_TYPES_STRING]);
+ if(*paths == NULL) {
+ closedir(dir);
return UA_STATUSCODE_BADOUTOFMEMORY;
}
- UA_ByteString_init(&context->localSymSigningKey);
- UA_ByteString_init(&context->localSymEncryptingKey);
- UA_ByteString_init(&context->localSymIv);
- UA_ByteString_init(&context->remoteSymSigningKey);
- UA_ByteString_init(&context->remoteSymEncryptingKey);
- UA_ByteString_init(&context->remoteSymIv);
-
- UA_StatusCode retval = UA_copyCertificate (&context->remoteCertificate,
- remoteCertificate);
- if (retval != UA_STATUSCODE_GOOD) {
- UA_free (context);
- return retval;
+ struct dirent *ent;
+ char buf2[PATH_MAX + 1];
+ char *res = realpath(buf, buf2);
+ if(!res) {
+ closedir(dir);
+ return UA_STATUSCODE_BADINTERNALERROR;
}
-
- /* decode to X509 */
- context->remoteCertificateX509 = UA_OpenSSL_LoadCertificate(&context->remoteCertificate);
- if (context->remoteCertificateX509 == NULL) {
- UA_ByteString_clear (&context->remoteCertificate);
- UA_free (context);
- return UA_STATUSCODE_BADCERTIFICATECHAININCOMPLETE;
+ size_t pathlen = strlen(buf2);
+ *pathsSize = 0;
+ while((ent = readdir (dir)) != NULL && *pathsSize < 256) {
+ if(ent->d_type != DT_REG)
+ continue;
+ buf2[pathlen] = '/';
+ buf2[pathlen+1] = 0;
+ strcat(buf2, ent->d_name);
+ (*paths)[*pathsSize] = UA_STRING_ALLOC(buf2);
+ *pathsSize += 1;
}
+ closedir(dir);
- context->policyContext = (Policy_Context_Basic128Rsa15 *)
- (securityPolicy->policyContext);
-
- *channelContext = context;
-
- UA_LOG_INFO (securityPolicy->logger,
- UA_LOGCATEGORY_SECURITYPOLICY,
- "The Basic128Rsa15 security policy channel with openssl is created.");
-
+ if(*pathsSize == 0) {
+ UA_free(*paths);
+ *paths = NULL;
+ }
return UA_STATUSCODE_GOOD;
}
-/* delete the channel context */
+static UA_StatusCode
+reloadCertificates(CertInfo *ci) {
+ UA_StatusCode retval = UA_STATUSCODE_GOOD;
+ int err = 0;
+ int internalErrorFlag = 0;
-static void
-UA_ChannelModule_Basic128Rsa15_Delete_Context (void * channelContext) {
- if (channelContext != NULL) {
- Channel_Context_Basic128Rsa15 * cc = (Channel_Context_Basic128Rsa15 *)
- channelContext;
- X509_free (cc->remoteCertificateX509);
- UA_ByteString_deleteMembers (&cc->remoteCertificate);
- UA_ByteString_deleteMembers (&cc->localSymSigningKey);
- UA_ByteString_deleteMembers (&cc->localSymEncryptingKey);
- UA_ByteString_deleteMembers (&cc->localSymIv);
- UA_ByteString_deleteMembers (&cc->remoteSymSigningKey);
- UA_ByteString_deleteMembers (&cc->remoteSymEncryptingKey);
- UA_ByteString_deleteMembers (&cc->remoteSymIv);
- UA_LOG_INFO (cc->policyContext->logger,
- UA_LOGCATEGORY_SECURITYPOLICY,
- "The Basic128Rsa15 security policy channel with openssl is deleted.");
+ /* Load the trustlists */
+ if(ci->trustListFolder.length > 0) {
+ UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "Reloading the trust-list");
+ mbedtls_x509_crt_free(&ci->certificateTrustList);
+ mbedtls_x509_crt_init(&ci->certificateTrustList);
- UA_free (cc);
+ char f[PATH_MAX];
+ memcpy(f, ci->trustListFolder.data, ci->trustListFolder.length);
+ f[ci->trustListFolder.length] = 0;
+ err = mbedtls_x509_crt_parse_path(&ci->certificateTrustList, f);
+ if(err == 0) {
+ UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
+ "Loaded certificate from %s", f);
+ } else {
+ char errBuff[300];
+ mbedtls_strerror(err, errBuff, 300);
+ UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
+ "Failed to load certificate from %s, mbedTLS error: %s (error code: %d)", f, errBuff, err);
+ internalErrorFlag = 1;
+ }
}
-}
-static UA_StatusCode
-UA_ChannelModule_Basic128Rsa15_setLocalSymSigningKey (void * channelContext,
- const UA_ByteString * key) {
- if (key == NULL || channelContext == NULL) {
- return UA_STATUSCODE_BADINVALIDARGUMENT;
+ /* Load the revocationlists */
+ if(ci->revocationListFolder.length > 0) {
+ UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "Reloading the revocation-list");
+ size_t pathsSize = 0;
+ UA_String *paths = NULL;
+ retval = fileNamesFromFolder(&ci->revocationListFolder, &pathsSize, &paths);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+ mbedtls_x509_crl_free(&ci->certificateRevocationList);
+ mbedtls_x509_crl_init(&ci->certificateRevocationList);
+ for(size_t i = 0; i < pathsSize; i++) {
+ char f[PATH_MAX];
+ memcpy(f, paths[i].data, paths[i].length);
+ f[paths[i].length] = 0;
+ err = mbedtls_x509_crl_parse_file(&ci->certificateRevocationList, f);
+ if(err == 0) {
+ UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
+ "Loaded certificate from %.*s",
+ (int)paths[i].length, paths[i].data);
+ } else {
+ char errBuff[300];
+ mbedtls_strerror(err, errBuff, 300);
+ UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
+ "Failed to load certificate from %.*s, mbedTLS error: %s (error code: %d)",
+ (int)paths[i].length, paths[i].data, errBuff, err);
+ internalErrorFlag = 1;
+ }
+ }
+ UA_Array_delete(paths, pathsSize, &UA_TYPES[UA_TYPES_STRING]);
+ paths = NULL;
+ pathsSize = 0;
}
- Channel_Context_Basic128Rsa15 * cc = (Channel_Context_Basic128Rsa15 *) channelContext;
- UA_ByteString_deleteMembers(&cc->localSymSigningKey);
- return UA_ByteString_copy(key, &cc->localSymSigningKey);
-}
-
-static UA_StatusCode
-UA_ChannelModule_Basic128Rsa15_setLocalSymEncryptingKey (void * channelContext,
- const UA_ByteString * key) {
- if (key == NULL || channelContext == NULL) {
- return UA_STATUSCODE_BADINVALIDARGUMENT;
+ /* Load the issuerlists */
+ if(ci->issuerListFolder.length > 0) {
+ UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "Reloading the issuer-list");
+ mbedtls_x509_crt_free(&ci->certificateIssuerList);
+ mbedtls_x509_crt_init(&ci->certificateIssuerList);
+ char f[PATH_MAX];
+ memcpy(f, ci->issuerListFolder.data, ci->issuerListFolder.length);
+ f[ci->issuerListFolder.length] = 0;
+ err = mbedtls_x509_crt_parse_path(&ci->certificateIssuerList, f);
+ if(err == 0) {
+ UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
+ "Loaded certificate from %s", f);
+ } else {
+ char errBuff[300];
+ mbedtls_strerror(err, errBuff, 300);
+ UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
+ "Failed to load certificate from %s, mbedTLS error: %s (error code: %d)",
+ f, errBuff, err);
+ internalErrorFlag = 1;
+ }
}
- Channel_Context_Basic128Rsa15 * cc = (Channel_Context_Basic128Rsa15 *) channelContext;
- UA_ByteString_deleteMembers(&cc->localSymEncryptingKey);
- return UA_ByteString_copy(key, &cc->localSymEncryptingKey);
-}
-
-static UA_StatusCode
-UA_ChannelModule_Basic128Rsa15_setLocalSymIv (void * channelContext,
- const UA_ByteString * iv) {
- if (iv == NULL || channelContext == NULL) {
- return UA_STATUSCODE_BADINVALIDARGUMENT;
+ if(internalErrorFlag) {
+ retval = UA_STATUSCODE_BADINTERNALERROR;
}
-
- Channel_Context_Basic128Rsa15 * cc = (Channel_Context_Basic128Rsa15 *) channelContext;
- UA_ByteString_deleteMembers(&cc->localSymIv);
- return UA_ByteString_copy(iv, &cc->localSymIv);
+ return retval;
}
-static UA_StatusCode
-UA_ChannelModule_Basic128Rsa15_setRemoteSymSigningKey (void * channelContext,
- const UA_ByteString * key) {
- if (key == NULL || channelContext == NULL) {
- return UA_STATUSCODE_BADINVALIDARGUMENT;
- }
+#endif
- Channel_Context_Basic128Rsa15 * cc = (Channel_Context_Basic128Rsa15 *) channelContext;
- UA_ByteString_deleteMembers(&cc->remoteSymSigningKey);
- return UA_ByteString_copy(key, &cc->remoteSymSigningKey);
+static UA_StatusCode
+certificateVerification_allow(void *verificationContext,
+ const UA_ByteString *certificate) {
+ return UA_STATUSCODE_GOOD;
}
static UA_StatusCode
-UA_ChannelModule_Basic128Rsa15_setRemoteSymEncryptingKey (void * channelContext,
- const UA_ByteString * key) {
- if (key == NULL || channelContext == NULL) {
- return UA_STATUSCODE_BADINVALIDARGUMENT;
- }
+certificateVerification_verify(void *verificationContext,
+ const UA_ByteString *certificate) {
+ CertInfo *ci = (CertInfo*)verificationContext;
+ if(!ci)
+ return UA_STATUSCODE_BADINTERNALERROR;
- Channel_Context_Basic128Rsa15 * cc = (Channel_Context_Basic128Rsa15 *) channelContext;
- UA_ByteString_deleteMembers(&cc->remoteSymEncryptingKey);
- return UA_ByteString_copy(key, &cc->remoteSymEncryptingKey);
-}
+#ifdef __linux__ /* Reload certificates if folder paths are specified */
+ UA_StatusCode certFlag = reloadCertificates(ci);
+ if(certFlag != UA_STATUSCODE_GOOD) {
+ return certFlag;
+ }
+#endif
-static UA_StatusCode
-UA_ChannelModule_Basic128Rsa15_setRemoteSymIv (void * channelContext,
- const UA_ByteString * key) {
- if (key == NULL || channelContext == NULL) {
- return UA_STATUSCODE_BADINVALIDARGUMENT;
+ if(ci->trustListFolder.length == 0 &&
+ ci->issuerListFolder.length == 0 &&
+ ci->revocationListFolder.length == 0 &&
+ ci->certificateTrustList.raw.len == 0 &&
+ ci->certificateIssuerList.raw.len == 0 &&
+ ci->certificateRevocationList.raw.len == 0) {
+ UA_LOG_WARNING(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
+ "PKI plugin unconfigured. Accepting the certificate.");
+ return UA_STATUSCODE_GOOD;
}
- Channel_Context_Basic128Rsa15 * cc = (Channel_Context_Basic128Rsa15 *) channelContext;
- UA_ByteString_deleteMembers(&cc->remoteSymIv);
- return UA_ByteString_copy(key, &cc->remoteSymIv);
-}
+ /* Parse the certificate */
+ mbedtls_x509_crt remoteCertificate;
-static UA_StatusCode
-UA_ChannelModule_Basic128Rsa15_compareCertificate (const void * channelContext,
- const UA_ByteString * certificate) {
- if(channelContext == NULL || certificate == NULL) {
- return UA_STATUSCODE_BADINVALIDARGUMENT;
- }
+ /* Temporary Object to parse the trustList */
+ mbedtls_x509_crt *tempCert = NULL;
- const Channel_Context_Basic128Rsa15 * cc =
- (const Channel_Context_Basic128Rsa15 *) channelContext;
- return UA_OpenSSL_X509_compare (certificate, cc->remoteCertificateX509);
-}
+ /* Temporary Object to parse the revocationList */
+ mbedtls_x509_crl *tempCrl = NULL;
-static UA_StatusCode
-UA_Asy_Basic128Rsa15_compareCertificateThumbprint (const UA_SecurityPolicy * securityPolicy,
- const UA_ByteString * certificateThumbprint) {
- if (securityPolicy == NULL || certificateThumbprint == NULL) {
- return UA_STATUSCODE_BADINVALIDARGUMENT;
- }
- Policy_Context_Basic128Rsa15 *pc = (Policy_Context_Basic128Rsa15 *)
- securityPolicy->policyContext;
- if(!UA_ByteString_equal(certificateThumbprint, &pc->localCertThumbprint)) {
- return UA_STATUSCODE_BADCERTIFICATEINVALID;
- }
- return UA_STATUSCODE_GOOD;
-}
+ /* Temporary Object to identify the parent CA when there is no intermediate CA */
+ mbedtls_x509_crt *parentCert = NULL;
-/* Generates a thumbprint for the specified certificate */
+ /* Temporary Object to identify the parent CA when there is intermediate CA */
+ mbedtls_x509_crt *parentCert_2 = NULL;
-static UA_StatusCode
-UA_Asy_Basic128Rsa15_makeCertificateThumbprint (const UA_SecurityPolicy * securityPolicy,
- const UA_ByteString * certificate,
- UA_ByteString * thumbprint) {
- return UA_Openssl_X509_GetCertificateThumbprint (certificate,
- thumbprint, false);
-}
+ /* Flag value to identify if the issuer certificate is found */
+ int issuerKnown = 0;
-static size_t
-UA_AsySig_Basic128Rsa15_getRemoteSignatureSize (const UA_SecurityPolicy * securityPolicy,
- const void * channelContext) {
- if (securityPolicy == NULL || channelContext == NULL) {
- return UA_STATUSCODE_BADINVALIDARGUMENT;
+ /* Flag value to identify if the parent certificate found */
+ int parentFound = 0;
+
+ mbedtls_x509_crt_init(&remoteCertificate);
+ int mbedErr = mbedtls_x509_crt_parse(&remoteCertificate, certificate->data,
+ certificate->length);
+ if(mbedErr) {
+ /* char errBuff[300]; */
+ /* mbedtls_strerror(mbedErr, errBuff, 300); */
+ /* UA_LOG_WARNING(data->policyContext->securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY, */
+ /* "Could not parse the remote certificate with error: %s", errBuff); */
+ return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
}
- const Channel_Context_Basic128Rsa15 * cc = (const Channel_Context_Basic128Rsa15 *) channelContext;
- UA_Int32 keyLen = 0;
- UA_Openssl_RSA_Public_GetKeyLength (cc->remoteCertificateX509, &keyLen);
- return (size_t) keyLen;
-}
+ /* Verify */
+ mbedtls_x509_crt_profile crtProfile = {
+ MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA1) | MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA256),
+ 0xFFFFFF, 0x000000, 128 * 8 // in bits
+ }; // TODO: remove magic numbers
-static size_t
-UA_AsySig_Basic128Rsa15_getLocalSignatureSize (const UA_SecurityPolicy * securityPolicy,
- const void * channelContext) {
- if (securityPolicy == NULL || channelContext == NULL) {
- return UA_STATUSCODE_BADINVALIDARGUMENT;
+ uint32_t flags = 0;
+ mbedErr = mbedtls_x509_crt_verify_with_profile(&remoteCertificate,
+ &ci->certificateTrustList,
+ &ci->certificateRevocationList,
+ &crtProfile, NULL, &flags, NULL, NULL);
+
+ /* Flag to check if the remote certificate is trusted or not */
+ int TRUSTED = 0;
+
+ /* Check if the remoteCertificate is present in the trustList while mbedErr value is not zero */
+ if(mbedErr && !(flags & MBEDTLS_X509_BADCERT_EXPIRED) && !(flags & MBEDTLS_X509_BADCERT_FUTURE)) {
+ for(tempCert = &ci->certificateTrustList; tempCert != NULL; tempCert = tempCert->next) {
+ if(remoteCertificate.raw.len == tempCert->raw.len &&
+ memcmp(remoteCertificate.raw.p, tempCert->raw.p, remoteCertificate.raw.len) == 0) {
+ TRUSTED = REMOTECERTIFICATETRUSTED;
+ break;
+ }
+ }
}
- Policy_Context_Basic128Rsa15 * pc =
- (Policy_Context_Basic128Rsa15 *) securityPolicy->policyContext;
- UA_Int32 keyLen = 0;
- UA_Openssl_RSA_Private_GetKeyLength (pc->localPrivateKey, &keyLen);
+ /* If the remote certificate is present in the trustList then check if the issuer certificate
+ * of remoteCertificate is present in issuerList */
+ if(TRUSTED && mbedErr) {
+ mbedErr = mbedtls_x509_crt_verify_with_profile(&remoteCertificate,
+ &ci->certificateIssuerList,
+ &ci->certificateRevocationList,
+ &crtProfile, NULL, &flags, NULL, NULL);
- return (size_t) keyLen;
-}
+ /* Check if the parent certificate has a CRL file available */
+ if(!mbedErr) {
+ /* Flag value to identify if that there is an intermediate CA present */
+ int dualParent = 0;
-static UA_StatusCode
-UA_AsySig_Basic128Rsa15_Verify (const UA_SecurityPolicy * securityPolicy,
- void * channelContext,
- const UA_ByteString * message,
- const UA_ByteString * signature) {
- if (securityPolicy == NULL || message == NULL || signature == NULL ||
- channelContext == NULL) {
- return UA_STATUSCODE_BADINVALIDARGUMENT;
- }
+ /* Identify the topmost parent certificate for the remoteCertificate */
+ for(parentCert = &ci->certificateIssuerList; parentCert != NULL; parentCert = parentCert->next ) {
+ if(memcmp(remoteCertificate.issuer_raw.p, parentCert->subject_raw.p, parentCert->subject_raw.len) == 0) {
+ for(parentCert_2 = &ci->certificateTrustList; parentCert_2 != NULL; parentCert_2 = parentCert_2->next) {
+ if(memcmp(parentCert->issuer_raw.p, parentCert_2->subject_raw.p, parentCert_2->subject_raw.len) == 0) {
+ dualParent = DUALPARENT;
+ break;
+ }
+ }
+ parentFound = PARENTFOUND;
+ }
- Channel_Context_Basic128Rsa15 * cc = (Channel_Context_Basic128Rsa15 *) channelContext;
- UA_StatusCode retval = UA_OpenSSL_RSA_PKCS1_V15_SHA1_Verify (message,
- cc->remoteCertificateX509, signature);
+ if(parentFound == PARENTFOUND)
+ break;
+ }
- return retval;
-}
+ /* Check if there is an intermediate certificate between the topmost parent
+ * certificate and child certificate
+ * If yes the topmost parent certificate is to be checked whether it has a
+ * CRL file avaiable */
+ if(dualParent == DUALPARENT && parentFound == PARENTFOUND) {
+ parentCert = parentCert_2;
+ }
-static UA_StatusCode
-UA_AsySig_Basic128Rsa15_Sign (const UA_SecurityPolicy * securityPolicy,
- void * channelContext,
- const UA_ByteString * message,
- UA_ByteString * signature) {
- if (securityPolicy == NULL || channelContext == NULL ||
- message == NULL || signature == NULL) {
- return UA_STATUSCODE_BADINVALIDARGUMENT;
- }
+ /* If a parent certificate is found traverse the revocationList and identify
+ * if there is any CRL file that corresponds to the parentCertificate */
+ if(parentFound == PARENTFOUND) {
+ tempCrl = &ci->certificateRevocationList;
+ while(tempCrl != NULL) {
+ if(tempCrl->version != 0 &&
+ tempCrl->issuer_raw.len == parentCert->subject_raw.len &&
+ memcmp(tempCrl->issuer_raw.p,
+ parentCert->subject_raw.p,
+ tempCrl->issuer_raw.len) == 0) {
+ issuerKnown = ISSUERKNOWN;
+ break;
+ }
- Policy_Context_Basic128Rsa15 * pc =
- (Policy_Context_Basic128Rsa15 *) securityPolicy->policyContext;
- return UA_Openssl_RSA_PKCS1_V15_SHA1_Sign (message, pc->localPrivateKey,
- signature);
-}
+ tempCrl = tempCrl->next;
+ }
-static size_t
-UA_AsymEn_Basic128Rsa15_getRemotePlainTextBlockSize (const UA_SecurityPolicy * securityPolicy,
- const void * channelContext) {
- if (securityPolicy == NULL || channelContext == NULL) {
- return UA_STATUSCODE_BADINVALIDARGUMENT;
- }
+ /* If the CRL file corresponding to the parent certificate is not present
+ * then return UA_STATUSCODE_BADCERTIFICATEISSUERREVOCATIONUNKNOWN */
+ if(!issuerKnown) {
+ return UA_STATUSCODE_BADCERTIFICATEISSUERREVOCATIONUNKNOWN;
+ }
- const Channel_Context_Basic128Rsa15 * cc = (const Channel_Context_Basic128Rsa15 *) channelContext;
- UA_Int32 keyLen = 0;
- UA_Openssl_RSA_Public_GetKeyLength (cc->remoteCertificateX509, &keyLen);
- return (size_t) keyLen - UA_SECURITYPOLICY_BASIC128RSA15_RSAPADDING_LEN;
-}
+ }
+
+ }
-static size_t
-UA_AsymEn_Basic128Rsa15_getRemoteBlockSize (const UA_SecurityPolicy * securityPolicy,
- const void * channelContext) {
- if (securityPolicy == NULL || channelContext == NULL) {
- return UA_STATUSCODE_BADINVALIDARGUMENT;
}
+ else if(!mbedErr && !TRUSTED) {
+ /* This else if section is to identify if the parent certificate which is present in trustList
+ * has CRL file corresponding to it */
- const Channel_Context_Basic128Rsa15 * cc = (const Channel_Context_Basic128Rsa15 *) channelContext;
- UA_Int32 keyLen = 0;
- UA_Openssl_RSA_Public_GetKeyLength (cc->remoteCertificateX509, &keyLen);
- return (size_t) keyLen;
-}
+ /* Identify the parent certificate of the remoteCertificate */
+ for(parentCert = &ci->certificateTrustList; parentCert != NULL; parentCert = parentCert->next) {
+ if(memcmp(remoteCertificate.issuer_raw.p, parentCert->subject_raw.p, parentCert->subject_raw.len) == 0) {
+ parentFound = PARENTFOUND;
+ break;
+ }
-static size_t
-UA_AsymEn_Basic128Rsa15_getRemoteKeyLength (const UA_SecurityPolicy * securityPolicy,
- const void * channelContext) {
- if (securityPolicy == NULL || channelContext == NULL)
- return UA_STATUSCODE_BADINVALIDARGUMENT;
+ }
- const Channel_Context_Basic128Rsa15 * cc = (const Channel_Context_Basic128Rsa15 *) channelContext;
- UA_Int32 keyLen = 0;
- UA_Openssl_RSA_Public_GetKeyLength (cc->remoteCertificateX509, &keyLen);
- return (size_t) keyLen * 8;
-}
+ /* If the parent certificate is found traverse the revocationList and identify
+ * if there is any CRL file that corresponds to the parentCertificate */
+ if(parentFound == PARENTFOUND &&
+ memcmp(remoteCertificate.issuer_raw.p, remoteCertificate.subject_raw.p, remoteCertificate.subject_raw.len) != 0) {
+ tempCrl = &ci->certificateRevocationList;
+ while(tempCrl != NULL) {
+ if(tempCrl->version != 0 &&
+ tempCrl->issuer_raw.len == parentCert->subject_raw.len &&
+ memcmp(tempCrl->issuer_raw.p,
+ parentCert->subject_raw.p,
+ tempCrl->issuer_raw.len) == 0) {
+ issuerKnown = ISSUERKNOWN;
+ break;
+ }
-static size_t
-UA_AsymEn_Basic128Rsa15_getLocalKeyLength (const UA_SecurityPolicy * securityPolicy,
- const void * channelContext) {
- if (securityPolicy == NULL || channelContext == NULL)
- return UA_STATUSCODE_BADINVALIDARGUMENT;
+ tempCrl = tempCrl->next;
+ }
- Policy_Context_Basic128Rsa15 * pc =
- (Policy_Context_Basic128Rsa15 *) securityPolicy->policyContext;
- UA_Int32 keyLen = 0;
- UA_Openssl_RSA_Private_GetKeyLength (pc->localPrivateKey, &keyLen);
+ /* If the CRL file corresponding to the parent certificate is not present
+ * then return UA_STATUSCODE_BADCERTIFICATEREVOCATIONUNKNOWN */
+ if(!issuerKnown) {
+ return UA_STATUSCODE_BADCERTIFICATEREVOCATIONUNKNOWN;
+ }
- return (size_t) keyLen * 8;
-}
+ }
-static UA_StatusCode
-UA_AsymEn_Basic128Rsa15_Decrypt (const UA_SecurityPolicy * securityPolicy,
- void * channelContext,
- UA_ByteString * data) {
- if (securityPolicy == NULL || channelContext == NULL || data == NULL) {
- return UA_STATUSCODE_BADINVALIDARGUMENT;
}
- Channel_Context_Basic128Rsa15 * cc = (Channel_Context_Basic128Rsa15 *) channelContext;
- UA_StatusCode ret = UA_Openssl_RSA_PKCS1_V15_Decrypt (data,
- cc->policyContext->localPrivateKey);
- return ret;
-}
+ // TODO: Extend verification
-static UA_StatusCode
-UA_AsymEn_Basic128Rsa15_Encrypt (const UA_SecurityPolicy * securityPolicy,
- void * channelContext,
- UA_ByteString * data) {
- if (securityPolicy == NULL || channelContext == NULL ||
- data == NULL)
- return UA_STATUSCODE_BADINVALIDARGUMENT;
+ /* This condition will check whether the certificate is a User certificate
+ * or a CA certificate. If the MBEDTLS_X509_KU_KEY_CERT_SIGN and
+ * MBEDTLS_X509_KU_CRL_SIGN of key_usage are set, then the certificate
+ * shall be condidered as CA Certificate and cannot be used to establish a
+ * connection. Refer the test case CTT/Security/Security Certificate Validation/029.js
+ * for more details */
+#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
+ if((remoteCertificate.key_usage & MBEDTLS_X509_KU_KEY_CERT_SIGN) &&
+ (remoteCertificate.key_usage & MBEDTLS_X509_KU_CRL_SIGN)) {
+ return UA_STATUSCODE_BADCERTIFICATEUSENOTALLOWED;
+ }
+#else
+ if((remoteCertificate.private_key_usage & MBEDTLS_X509_KU_KEY_CERT_SIGN) &&
+ (remoteCertificate.private_key_usage & MBEDTLS_X509_KU_CRL_SIGN)) {
+ return UA_STATUSCODE_BADCERTIFICATEUSENOTALLOWED;
+ }
+#endif
- Channel_Context_Basic128Rsa15 * cc = (Channel_Context_Basic128Rsa15 *) channelContext;
- return UA_Openssl_RSA_PKCS1_V15_Encrypt (data,
- UA_SECURITYPOLICY_BASIC128RSA15_RSAPADDING_LEN,
- cc->remoteCertificateX509);
-}
-static UA_StatusCode
-UA_Sym_Basic128Rsa15_generateNonce (const UA_SecurityPolicy * sp,
- UA_ByteString * out) {
- UA_Int32 rc = RAND_bytes(out->data, (int) out->length);
- if (rc != 1) {
- return UA_STATUSCODE_BADUNEXPECTEDERROR;
+ UA_StatusCode retval = UA_STATUSCODE_GOOD;
+ if(mbedErr) {
+#if UA_LOGLEVEL <= 400
+ char buff[100];
+ int len = mbedtls_x509_crt_verify_info(buff, 100, "", flags);
+ UA_LOG_WARNING(UA_Log_Stdout, UA_LOGCATEGORY_SECURITYPOLICY,
+ "Verifying the certificate failed with error: %.*s", len-1, buff);
+#endif
+ if(flags & (uint32_t)MBEDTLS_X509_BADCERT_NOT_TRUSTED) {
+ retval = UA_STATUSCODE_BADCERTIFICATEUNTRUSTED;
+ } else if(flags & (uint32_t)MBEDTLS_X509_BADCERT_FUTURE ||
+ flags & (uint32_t)MBEDTLS_X509_BADCERT_EXPIRED) {
+ retval = UA_STATUSCODE_BADCERTIFICATETIMEINVALID;
+ } else if(flags & (uint32_t)MBEDTLS_X509_BADCERT_REVOKED ||
+ flags & (uint32_t)MBEDTLS_X509_BADCRL_EXPIRED) {
+ retval = UA_STATUSCODE_BADCERTIFICATEREVOKED;
+ } else {
+ retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
+ }
}
- return UA_STATUSCODE_GOOD;
-}
-static UA_StatusCode
-UA_Sym_Basic128Rsa15_generateKey (const UA_SecurityPolicy * securityPolicy,
- const UA_ByteString * secret,
- const UA_ByteString * seed,
- UA_ByteString * out) {
- return UA_Openssl_Random_Key_PSHA1_Derive (secret, seed, out);
+ mbedtls_x509_crt_free(&remoteCertificate);
+ return retval;
}
-static size_t
-UA_SymEn_Basic128Rsa15_getLocalKeyLength (const UA_SecurityPolicy * securityPolicy,
- const void * channelContext) {
- /* 16 bytes 128 bits */
- return UA_SECURITYPOLICY_BASIC128RSA15_SYM_ENCRYPTION_KEY_LENGTH;
-}
+static UA_StatusCode
+certificateVerification_verifyApplicationURI(void *verificationContext,
+ const UA_ByteString *certificate,
+ const UA_String *applicationURI) {
+ CertInfo *ci = (CertInfo*)verificationContext;
+ if(!ci)
+ return UA_STATUSCODE_BADINTERNALERROR;
-static size_t
-UA_SymEn_Basic128Rsa15_getBlockSize (const UA_SecurityPolicy * securityPolicy,
- const void * channelContext) {
- return UA_SECURITYPOLICY_BASIC128RSA15_SYM_ENCRYPTION_BLOCK_SIZE;
-}
+ /* Parse the certificate */
+ mbedtls_x509_crt remoteCertificate;
+ mbedtls_x509_crt_init(&remoteCertificate);
+ int mbedErr = mbedtls_x509_crt_parse(&remoteCertificate, certificate->data,
+ certificate->length);
+ if(mbedErr)
+ return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
-static size_t
-UA_SymEn_Basic128Rsa15_getRemoteKeyLength (const UA_SecurityPolicy * securityPolicy,
- const void * channelContext) {
- return UA_SECURITYPOLICY_BASIC128RSA15_SYM_ENCRYPTION_KEY_LENGTH;
-}
+ /* Poor man's ApplicationUri verification. mbedTLS does not parse all fields
+ * of the Alternative Subject Name. Instead test whether the URI-string is
+ * present in the v3_ext field in general.
+ *
+ * TODO: Improve parsing of the Alternative Subject Name */
+ UA_StatusCode retval = UA_STATUSCODE_GOOD;
+ if(UA_Bstrstr(remoteCertificate.v3_ext.p, remoteCertificate.v3_ext.len,
+ applicationURI->data, applicationURI->length) == NULL)
+ retval = UA_STATUSCODE_BADCERTIFICATEURIINVALID;
-static size_t
-UA_SymEn_Basic128Rsa15_getPlainTextBlockSize (const UA_SecurityPolicy * securityPolicy,
- const void * channelContext) {
- return UA_SECURITYPOLICY_BASIC128RSA15_SYM_PLAIN_TEXT_BLOCK_SIZE;
+ mbedtls_x509_crt_free(&remoteCertificate);
+ return retval;
}
-static UA_StatusCode
-UA_SymEn_Basic128Rsa15_Encrypt (const UA_SecurityPolicy * securityPolicy,
- void * channelContext,
- UA_ByteString * data) {
- if(securityPolicy == NULL || channelContext == NULL || data == NULL)
- return UA_STATUSCODE_BADINVALIDARGUMENT;
-
- Channel_Context_Basic128Rsa15 * cc = (Channel_Context_Basic128Rsa15 *) channelContext;
- return UA_OpenSSL_AES_128_CBC_Encrypt (&cc->localSymIv, &cc->localSymEncryptingKey, data);
+static void
+certificateVerification_clear(UA_CertificateVerification *cv) {
+ CertInfo *ci = (CertInfo*)cv->context;
+ if(!ci)
+ return;
+ mbedtls_x509_crt_free(&ci->certificateTrustList);
+ mbedtls_x509_crl_free(&ci->certificateRevocationList);
+ mbedtls_x509_crt_free(&ci->certificateIssuerList);
+ UA_String_clear(&ci->trustListFolder);
+ UA_String_clear(&ci->issuerListFolder);
+ UA_String_clear(&ci->revocationListFolder);
+ UA_free(ci);
+ cv->context = NULL;
}
-static UA_StatusCode
-UA_SymEn_Basic128Rsa15_Decrypt (const UA_SecurityPolicy * securityPolicy,
- void * channelContext,
- UA_ByteString * data) {
- if(securityPolicy == NULL || channelContext == NULL || data == NULL)
- return UA_STATUSCODE_BADINVALIDARGUMENT;
- Channel_Context_Basic128Rsa15 * cc = (Channel_Context_Basic128Rsa15 *) channelContext;
- return UA_OpenSSL_AES_128_CBC_Decrypt (&cc->remoteSymIv, &cc->remoteSymEncryptingKey, data);
-}
+UA_StatusCode
+UA_CertificateVerification_Trustlist(UA_CertificateVerification *cv,
+ const UA_ByteString *certificateTrustList,
+ size_t certificateTrustListSize,
+ const UA_ByteString *certificateIssuerList,
+ size_t certificateIssuerListSize,
+ const UA_ByteString *certificateRevocationList,
+ size_t certificateRevocationListSize) {
+ CertInfo *ci = (CertInfo*)UA_malloc(sizeof(CertInfo));
+ if(!ci)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ memset(ci, 0, sizeof(CertInfo));
+ mbedtls_x509_crt_init(&ci->certificateTrustList);
+ mbedtls_x509_crl_init(&ci->certificateRevocationList);
+ mbedtls_x509_crt_init(&ci->certificateIssuerList);
-static size_t
-UA_SymSig_Basic128Rsa15_getKeyLength (const UA_SecurityPolicy * securityPolicy,
- const void * channelContext) {
- return UA_SECURITYPOLICY_BASIC128RSA15_SYM_SIGNING_KEY_LENGTH;
-}
+ cv->context = (void*)ci;
+ if(certificateTrustListSize > 0)
+ cv->verifyCertificate = certificateVerification_verify;
+ else
+ cv->verifyCertificate = certificateVerification_allow;
+ cv->clear = certificateVerification_clear;
+ cv->verifyApplicationURI = certificateVerification_verifyApplicationURI;
-static size_t
-UA_SymSig_Basic128Rsa15_getSignatureSize (const UA_SecurityPolicy * securityPolicy,
- const void * channelContext) {
- return UA_SHA1_LENGTH;
-}
+ int err;
+ UA_ByteString data;
+ UA_ByteString_init(&data);
-static UA_StatusCode
-UA_SymSig_Basic128Rsa15_Verify (const UA_SecurityPolicy * securityPolicy,
- void * channelContext,
- const UA_ByteString * message,
- const UA_ByteString * signature) {
- if (securityPolicy == NULL || channelContext == NULL ||
- message == NULL || signature == NULL)
- return UA_STATUSCODE_BADINVALIDARGUMENT;
-
- Channel_Context_Basic128Rsa15 * cc = (Channel_Context_Basic128Rsa15 *) channelContext;
- return UA_OpenSSL_HMAC_SHA1_Verify (message,
- &cc->remoteSymSigningKey,
- signature);
-}
+ for(size_t i = 0; i < certificateTrustListSize; i++) {
+ data = copyDataFormatAware(&certificateTrustList[i]);
+ err = mbedtls_x509_crt_parse(&ci->certificateTrustList,
+ data.data,
+ data.length);
+ UA_ByteString_clear(&data);
+ if(err)
+ goto error;
+ }
+ for(size_t i = 0; i < certificateIssuerListSize; i++) {
+ data = copyDataFormatAware(&certificateIssuerList[i]);
+ err = mbedtls_x509_crt_parse(&ci->certificateIssuerList,
+ data.data,
+ data.length);
+ UA_ByteString_clear(&data);
+ if(err)
+ goto error;
+ }
+ for(size_t i = 0; i < certificateRevocationListSize; i++) {
+ data = copyDataFormatAware(&certificateRevocationList[i]);
+ err = mbedtls_x509_crl_parse(&ci->certificateRevocationList,
+ data.data,
+ data.length);
+ UA_ByteString_clear(&data);
+ if(err)
+ goto error;
+ }
-static UA_StatusCode
-UA_SymSig_Basic128Rsa15_Sign (const UA_SecurityPolicy * securityPolicy,
- void * channelContext,
- const UA_ByteString * message,
- UA_ByteString * signature) {
- if (securityPolicy == NULL || channelContext == NULL ||
- message == NULL || signature == NULL)
- return UA_STATUSCODE_BADINVALIDARGUMENT;
-
- Channel_Context_Basic128Rsa15 * cc = (Channel_Context_Basic128Rsa15 *) channelContext;
- return UA_OpenSSL_HMAC_SHA1_Sign (message, &cc->localSymSigningKey, signature);
+ return UA_STATUSCODE_GOOD;
+error:
+ certificateVerification_clear(cv);
+ return UA_STATUSCODE_BADINTERNALERROR;
}
-/* the main entry of Basic128Rsa15 */
+#ifdef __linux__ /* Linux only so far */
UA_StatusCode
-UA_SecurityPolicy_Basic128Rsa15 (UA_SecurityPolicy * policy,
- const UA_ByteString localCertificate,
- const UA_ByteString localPrivateKey,
- const UA_Logger * logger) {
+UA_CertificateVerification_CertFolders(UA_CertificateVerification *cv,
+ const char *trustListFolder,
+ const char *issuerListFolder,
+ const char *revocationListFolder) {
+ CertInfo *ci = (CertInfo*)UA_malloc(sizeof(CertInfo));
+ if(!ci)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ memset(ci, 0, sizeof(CertInfo));
+ mbedtls_x509_crt_init(&ci->certificateTrustList);
+ mbedtls_x509_crl_init(&ci->certificateRevocationList);
+ mbedtls_x509_crt_init(&ci->certificateIssuerList);
- UA_SecurityPolicyAsymmetricModule * const asymmetricModule = &policy->asymmetricModule;
- UA_SecurityPolicySymmetricModule * const symmetricModule = &policy->symmetricModule;
- UA_SecurityPolicyChannelModule * const channelModule = &policy->channelModule;
- UA_StatusCode retval;
+ /* Only set the folder paths. They will be reloaded during runtime.
+ * TODO: Add a more efficient reloading of only the changes */
+ ci->trustListFolder = UA_STRING_ALLOC(trustListFolder);
+ ci->issuerListFolder = UA_STRING_ALLOC(issuerListFolder);
+ ci->revocationListFolder = UA_STRING_ALLOC(revocationListFolder);
- UA_LOG_INFO (logger, UA_LOGCATEGORY_SECURITYPOLICY,
- "The Basic128Rsa15 security policy with openssl is added.");
+ reloadCertificates(ci);
- UA_Openssl_Init ();
- memset(policy, 0, sizeof(UA_SecurityPolicy));
- policy->logger = logger;
- policy->policyUri = UA_STRING("http://opcfoundation.org/UA/SecurityPolicy#Basic128Rsa15\0");
+ cv->context = (void*)ci;
+ cv->verifyCertificate = certificateVerification_verify;
+ cv->clear = certificateVerification_clear;
+ cv->verifyApplicationURI = certificateVerification_verifyApplicationURI;
- /* set ChannelModule context */
+ return UA_STATUSCODE_GOOD;
+}
- channelModule->newContext = UA_ChannelModule_Basic128Rsa15_New_Context;
- channelModule->deleteContext = UA_ChannelModule_Basic128Rsa15_Delete_Context;
+#endif
+#endif
- channelModule->setLocalSymSigningKey = UA_ChannelModule_Basic128Rsa15_setLocalSymSigningKey;
- channelModule->setLocalSymEncryptingKey = UA_ChannelModule_Basic128Rsa15_setLocalSymEncryptingKey;
- channelModule->setLocalSymIv = UA_ChannelModule_Basic128Rsa15_setLocalSymIv;
- channelModule->setRemoteSymSigningKey = UA_ChannelModule_Basic128Rsa15_setRemoteSymSigningKey;
- channelModule->setRemoteSymEncryptingKey = UA_ChannelModule_Basic128Rsa15_setRemoteSymEncryptingKey;
- channelModule->setRemoteSymIv = UA_ChannelModule_Basic128Rsa15_setRemoteSymIv;
- channelModule->compareCertificate = UA_ChannelModule_Basic128Rsa15_compareCertificate;
+/**** amalgamated original file "/plugins/crypto/mbedtls/securitypolicy_mbedtls_common.c" ****/
- retval = UA_OpenSSL_LoadLocalCertificate(&localCertificate, &policy->localCertificate);
- if (retval != UA_STATUSCODE_GOOD)
- return retval;
+#if defined(UA_ENABLE_ENCRYPTION_MBEDTLS) || defined(UA_ENABLE_PUBSUB_ENCRYPTION)
- /* asymmetricModule */
- asymmetricModule->compareCertificateThumbprint = UA_Asy_Basic128Rsa15_compareCertificateThumbprint;
- asymmetricModule->makeCertificateThumbprint = UA_Asy_Basic128Rsa15_makeCertificateThumbprint;
+#include <mbedtls/aes.h>
+#include <mbedtls/ctr_drbg.h>
+#include <mbedtls/entropy.h>
+#include <mbedtls/error.h>
+#include <mbedtls/md.h>
+#include <mbedtls/sha1.h>
+#include <mbedtls/version.h>
+#include <mbedtls/x509_crt.h>
- /* AsymmetricModule - signature algorithm */
+void
+swapBuffers(UA_ByteString *const bufA, UA_ByteString *const bufB) {
+ UA_ByteString tmp = *bufA;
+ *bufA = *bufB;
+ *bufB = tmp;
+}
- UA_SecurityPolicySignatureAlgorithm * asySigAlgorithm =
- &asymmetricModule->cryptoModule.signatureAlgorithm;
- asySigAlgorithm->uri = UA_STRING("http://www.w3.org/2000/09/xmldsig#rsa-sha1\0");
- asySigAlgorithm->getRemoteSignatureSize = UA_AsySig_Basic128Rsa15_getRemoteSignatureSize;
- asySigAlgorithm->getLocalSignatureSize = UA_AsySig_Basic128Rsa15_getLocalSignatureSize;
- asySigAlgorithm->getLocalKeyLength = NULL;
- asySigAlgorithm->getRemoteKeyLength = NULL;
- asySigAlgorithm->verify = UA_AsySig_Basic128Rsa15_Verify;
- asySigAlgorithm->sign = UA_AsySig_Basic128Rsa15_Sign;
+void
+mbedtls_hmac(mbedtls_md_context_t *context, const UA_ByteString *key,
+ const UA_ByteString *in, unsigned char *out) {
+ mbedtls_md_hmac_starts(context, key->data, key->length);
+ mbedtls_md_hmac_update(context, in->data, in->length);
+ mbedtls_md_hmac_finish(context, out);
+}
- /* AsymmetricModule encryption algorithm */
+UA_StatusCode
+mbedtls_generateKey(mbedtls_md_context_t *context,
+ const UA_ByteString *secret, const UA_ByteString *seed,
+ UA_ByteString *out) {
+#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
+ size_t hashLen = (size_t)mbedtls_md_get_size(context->md_info);
+#else
+ size_t hashLen = (size_t)mbedtls_md_get_size(context->private_md_info);
+#endif
- UA_SecurityPolicyEncryptionAlgorithm * asymEncryAlg =
- &asymmetricModule->cryptoModule.encryptionAlgorithm;
- asymEncryAlg->uri = UA_STRING("http://www.w3.org/2001/04/xmlenc#rsa-1_5\0");
- asymEncryAlg->getRemotePlainTextBlockSize = UA_AsymEn_Basic128Rsa15_getRemotePlainTextBlockSize;
- asymEncryAlg->getRemoteBlockSize = UA_AsymEn_Basic128Rsa15_getRemoteBlockSize;
- asymEncryAlg->getRemoteKeyLength = UA_AsymEn_Basic128Rsa15_getRemoteKeyLength;
- asymEncryAlg->getLocalKeyLength = UA_AsymEn_Basic128Rsa15_getLocalKeyLength;
- asymEncryAlg->getLocalPlainTextBlockSize = NULL;
- asymEncryAlg->getLocalBlockSize = NULL;
- asymEncryAlg->decrypt = UA_AsymEn_Basic128Rsa15_Decrypt;
- asymEncryAlg->encrypt = UA_AsymEn_Basic128Rsa15_Encrypt;
+ UA_ByteString A_and_seed;
+ UA_ByteString_allocBuffer(&A_and_seed, hashLen + seed->length);
+ memcpy(A_and_seed.data + hashLen, seed->data, seed->length);
- /* SymmetricModule */
+ UA_ByteString ANext_and_seed;
+ UA_ByteString_allocBuffer(&ANext_and_seed, hashLen + seed->length);
+ memcpy(ANext_and_seed.data + hashLen, seed->data, seed->length);
- symmetricModule->secureChannelNonceLength = 16; /* 128 bits*/
- symmetricModule->generateNonce = UA_Sym_Basic128Rsa15_generateNonce;
- symmetricModule->generateKey = UA_Sym_Basic128Rsa15_generateKey;
+ UA_ByteString A = {
+ hashLen,
+ A_and_seed.data
+ };
- /* Symmetric encryption Algorithm */
+ UA_ByteString ANext = {
+ hashLen,
+ ANext_and_seed.data
+ };
- UA_SecurityPolicyEncryptionAlgorithm * symEncryptionAlgorithm =
- &symmetricModule->cryptoModule.encryptionAlgorithm;
- symEncryptionAlgorithm->uri = UA_STRING("http://www.w3.org/2001/04/xmlenc#aes128-cbc\0");
- symEncryptionAlgorithm->getLocalKeyLength = UA_SymEn_Basic128Rsa15_getLocalKeyLength;
- symEncryptionAlgorithm->getLocalBlockSize = UA_SymEn_Basic128Rsa15_getBlockSize;
- symEncryptionAlgorithm->getRemoteKeyLength = UA_SymEn_Basic128Rsa15_getRemoteKeyLength;
- symEncryptionAlgorithm->getRemoteBlockSize = UA_SymEn_Basic128Rsa15_getBlockSize;
- symEncryptionAlgorithm->getLocalPlainTextBlockSize = UA_SymEn_Basic128Rsa15_getPlainTextBlockSize;
- symEncryptionAlgorithm->getRemotePlainTextBlockSize = UA_SymEn_Basic128Rsa15_getPlainTextBlockSize;
- symEncryptionAlgorithm->decrypt = UA_SymEn_Basic128Rsa15_Decrypt;
- symEncryptionAlgorithm->encrypt = UA_SymEn_Basic128Rsa15_Encrypt;
+ mbedtls_hmac(context, secret, seed, A.data);
- /* Symmetric signature Algorithm */
+ UA_StatusCode retval = 0;
+ for(size_t offset = 0; offset < out->length; offset += hashLen) {
+ UA_ByteString outSegment = {
+ hashLen,
+ out->data + offset
+ };
+ UA_Boolean bufferAllocated = UA_FALSE;
+ // Not enough room in out buffer to write the hash.
+ if(offset + hashLen > out->length) {
+ outSegment.data = NULL;
+ outSegment.length = 0;
+ retval = UA_ByteString_allocBuffer(&outSegment, hashLen);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_ByteString_clear(&A_and_seed);
+ UA_ByteString_clear(&ANext_and_seed);
+ return retval;
+ }
+ bufferAllocated = UA_TRUE;
+ }
- UA_SecurityPolicySignatureAlgorithm * symSignatureAlgorithm =
- &symmetricModule->cryptoModule.signatureAlgorithm;
- symSignatureAlgorithm->uri = UA_STRING("http://www.w3.org/2000/09/xmldsig#hmac-sha1\0");
- symSignatureAlgorithm->getLocalKeyLength = UA_SymSig_Basic128Rsa15_getKeyLength;
- symSignatureAlgorithm->getRemoteKeyLength = UA_SymSig_Basic128Rsa15_getKeyLength;
- symSignatureAlgorithm->getRemoteSignatureSize = UA_SymSig_Basic128Rsa15_getSignatureSize;
- symSignatureAlgorithm->getLocalSignatureSize = UA_SymSig_Basic128Rsa15_getSignatureSize;
+ mbedtls_hmac(context, secret, &A_and_seed, outSegment.data);
+ mbedtls_hmac(context, secret, &A, ANext.data);
- symSignatureAlgorithm->verify = UA_SymSig_Basic128Rsa15_Verify;
- symSignatureAlgorithm->sign = UA_SymSig_Basic128Rsa15_Sign;
+ if(retval != UA_STATUSCODE_GOOD) {
+ if(bufferAllocated)
+ UA_ByteString_clear(&outSegment);
+ UA_ByteString_clear(&A_and_seed);
+ UA_ByteString_clear(&ANext_and_seed);
+ return retval;
+ }
- /* set the policy context */
+ if(bufferAllocated) {
+ memcpy(out->data + offset, outSegment.data, out->length - offset);
+ UA_ByteString_clear(&outSegment);
+ }
- retval = UA_Policy_Basic128Rsa15_New_Context (policy, localPrivateKey, logger);
- if (retval != UA_STATUSCODE_GOOD) {
- UA_ByteString_clear (&policy->localCertificate);
- return retval;
+ swapBuffers(&ANext_and_seed, &A_and_seed);
+ swapBuffers(&ANext, &A);
}
- policy->clear = UA_Policy_Basic128Rsa15_Clear_Context;
-
- /* Use the same signature algorithm as the asymmetric component for
- certificate signing (see standard) */
- policy->certificateSigningAlgorithm = policy->asymmetricModule.cryptoModule.signatureAlgorithm;
+ UA_ByteString_clear(&A_and_seed);
+ UA_ByteString_clear(&ANext_and_seed);
return UA_STATUSCODE_GOOD;
}
+UA_StatusCode
+mbedtls_verifySig_sha1(mbedtls_x509_crt *certificate, const UA_ByteString *message,
+ const UA_ByteString *signature) {
+ /* Compute the sha1 hash */
+ unsigned char hash[UA_SHA1_LENGTH];
+#if MBEDTLS_VERSION_NUMBER >= 0x02070000 && MBEDTLS_VERSION_NUMBER < 0x03000000
+ mbedtls_sha1_ret(message->data, message->length, hash);
+#else
+ mbedtls_sha1(message->data, message->length, hash);
#endif
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/plugins/securityPolicies/openssl/ua_openssl_basic256.c" ***********************************/
-
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- *
- * Copyright 2020 (c) Wind River Systems, Inc.
- * Copyright 2020 (c) basysKom GmbH
- */
+ /* Set the RSA settings */
+ mbedtls_rsa_context *rsaContext = mbedtls_pk_rsa(certificate->pk);
+ if(!rsaContext)
+ return UA_STATUSCODE_BADINTERNALERROR;
+ mbedtls_rsa_set_padding(rsaContext, MBEDTLS_RSA_PKCS_V15, MBEDTLS_MD_NONE);
-/*
-modification history
---------------------
-12mar20,lan written
-*/
+ /* Verify */
+ int mbedErr = mbedtls_pk_verify(&certificate->pk,
+ MBEDTLS_MD_SHA1, hash, UA_SHA1_LENGTH,
+ signature->data, signature->length);
+ if(mbedErr)
+ return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
+ return UA_STATUSCODE_GOOD;
+}
+UA_StatusCode
+mbedtls_sign_sha1(mbedtls_pk_context *localPrivateKey,
+ mbedtls_ctr_drbg_context *drbgContext,
+ const UA_ByteString *message,
+ UA_ByteString *signature) {
+ unsigned char hash[UA_SHA1_LENGTH];
+#if MBEDTLS_VERSION_NUMBER >= 0x02070000 && MBEDTLS_VERSION_NUMBER < 0x03000000
+ mbedtls_sha1_ret(message->data, message->length, hash);
+#else
+ mbedtls_sha1(message->data, message->length, hash);
+#endif
-#ifdef UA_ENABLE_ENCRYPTION_OPENSSL
+ mbedtls_rsa_context *rsaContext = mbedtls_pk_rsa(*localPrivateKey);
+ mbedtls_rsa_set_padding(rsaContext, MBEDTLS_RSA_PKCS_V15, MBEDTLS_MD_NONE);
+ size_t sigLen = 0;
+ int mbedErr = mbedtls_pk_sign(localPrivateKey, MBEDTLS_MD_SHA1, hash,
+ UA_SHA1_LENGTH, signature->data,
+#if MBEDTLS_VERSION_NUMBER >= 0x03000000
+ signature->length,
+#endif
+ &sigLen,
+ mbedtls_ctr_drbg_random, drbgContext);
+ if(mbedErr)
+ return UA_STATUSCODE_BADINTERNALERROR;
+ return UA_STATUSCODE_GOOD;
+}
-#include <openssl/x509.h>
-#include <openssl/rand.h>
+UA_StatusCode
+mbedtls_thumbprint_sha1(const UA_ByteString *certificate,
+ UA_ByteString *thumbprint) {
+ if(UA_ByteString_equal(certificate, &UA_BYTESTRING_NULL))
+ return UA_STATUSCODE_BADINTERNALERROR;
-#define UA_SECURITYPOLICY_BASIC256SHA1_RSAPADDING_LEN 42
-#define UA_SECURITYPOLICY_BASIC256_SYM_ENCRYPTION_KEY_LENGTH 32
-#define UA_SECURITYPOLICY_BASIC256_SYM_ENCRYPTION_BLOCK_SIZE 16
-#define UA_SECURITYPOLICY_BASIC256_SYM_PLAIN_TEXT_BLOCK_SIZE 16
-#define UA_SECURITYPOLICY_BASIC256_SYM_SIGNING_KEY_LENGTH 24
-#define UA_SHA1_LENGTH 20
+ if(thumbprint->length != UA_SHA1_LENGTH)
+ return UA_STATUSCODE_BADINTERNALERROR;
-typedef struct {
- EVP_PKEY * localPrivateKey;
- UA_ByteString localCertThumbprint;
- const UA_Logger * logger;
-} Policy_Context_Basic256;
+ /* The certificate thumbprint is always a 20 bit sha1 hash, see Part 4 of the Specification. */
+#if MBEDTLS_VERSION_NUMBER >= 0x02070000 && MBEDTLS_VERSION_NUMBER < 0x03000000
+ mbedtls_sha1_ret(certificate->data, certificate->length, thumbprint->data);
+#else
+ mbedtls_sha1(certificate->data, certificate->length, thumbprint->data);
+#endif
+ return UA_STATUSCODE_GOOD;
+}
-typedef struct {
- UA_ByteString localSymSigningKey;
- UA_ByteString localSymEncryptingKey;
- UA_ByteString localSymIv;
- UA_ByteString remoteSymSigningKey;
- UA_ByteString remoteSymEncryptingKey;
- UA_ByteString remoteSymIv;
+UA_StatusCode
+mbedtls_encrypt_rsaOaep(mbedtls_rsa_context *context,
+ mbedtls_ctr_drbg_context *drbgContext,
+ UA_ByteString *data, const size_t plainTextBlockSize) {
+ if(data->length % plainTextBlockSize != 0)
+ return UA_STATUSCODE_BADINTERNALERROR;
- Policy_Context_Basic256 * policyContext;
- UA_ByteString remoteCertificate;
- X509 * remoteCertificateX509;
-} Channel_Context_Basic256;
+ size_t max_blocks = data->length / plainTextBlockSize;
-static UA_StatusCode
-UA_Policy_Basic256_New_Context (UA_SecurityPolicy * securityPolicy,
- const UA_ByteString localPrivateKey,
- const UA_Logger * logger) {
- Policy_Context_Basic256 * context = (Policy_Context_Basic256 *)
- UA_malloc (sizeof (Policy_Context_Basic256));
- if (context == NULL) {
- return UA_STATUSCODE_BADOUTOFMEMORY;
- }
-
- context->localPrivateKey = UA_OpenSSL_LoadPrivateKey(&localPrivateKey);
- if (!context->localPrivateKey) {
- UA_free (context);
- return UA_STATUSCODE_BADINVALIDARGUMENT;
- }
+ UA_ByteString encrypted;
+#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
+ UA_StatusCode retval = UA_ByteString_allocBuffer(&encrypted, max_blocks * context->len);
+#else
+ size_t keylen = mbedtls_rsa_get_len(context);
+ UA_StatusCode retval = UA_ByteString_allocBuffer(&encrypted, max_blocks * keylen);
- UA_StatusCode retval = UA_Openssl_X509_GetCertificateThumbprint (
- &securityPolicy->localCertificate,
- &context->localCertThumbprint, true
- );
- if (retval != UA_STATUSCODE_GOOD) {
- EVP_PKEY_free(context->localPrivateKey);
- UA_free (context);
- return retval;
- }
+#endif
- context->logger = logger;
- securityPolicy->policyContext = context;
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
- return UA_STATUSCODE_GOOD;
-}
+ size_t lenDataToEncrypt = data->length;
+ size_t inOffset = 0;
+ size_t offset = 0;
+ const unsigned char *label = NULL;
+ while(lenDataToEncrypt >= plainTextBlockSize) {
+#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
+ int mbedErr = mbedtls_rsa_rsaes_oaep_encrypt(context, mbedtls_ctr_drbg_random,
+ drbgContext, MBEDTLS_RSA_PUBLIC,
+ label, 0, plainTextBlockSize,
+ data->data + inOffset, encrypted.data + offset);
+#else
+ int mbedErr = mbedtls_rsa_rsaes_oaep_encrypt(context, mbedtls_ctr_drbg_random,
+ drbgContext, label, 0, plainTextBlockSize,
+ data->data + inOffset, encrypted.data + offset);
+#endif
-static void
-UA_Policy_Basic256_Clear_Context (UA_SecurityPolicy *policy) {
- if (policy == NULL) {
- return;
- }
- UA_ByteString_deleteMembers(&policy->localCertificate);
+ if(mbedErr) {
+ UA_ByteString_clear(&encrypted);
+ return UA_STATUSCODE_BADINTERNALERROR;
+ }
- Policy_Context_Basic256 * ctx = (Policy_Context_Basic256 *) policy->policyContext;
- if (ctx == NULL) {
- return;
+ inOffset += plainTextBlockSize;
+#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
+ offset += context->len;
+#else
+ offset += keylen;
+#endif
+ lenDataToEncrypt -= plainTextBlockSize;
}
- /* delete all allocated members in the context */
-
- EVP_PKEY_free(ctx->localPrivateKey);
- UA_ByteString_deleteMembers (&ctx->localCertThumbprint);
- UA_free (ctx);
-
- return;
+ memcpy(data->data, encrypted.data, offset);
+ UA_ByteString_clear(&encrypted);
+ return UA_STATUSCODE_GOOD;
}
-/* create the channel context */
+UA_StatusCode
+mbedtls_decrypt_rsaOaep(mbedtls_pk_context *localPrivateKey,
+ mbedtls_ctr_drbg_context *drbgContext,
+ UA_ByteString *data) {
+ mbedtls_rsa_context *rsaContext = mbedtls_pk_rsa(*localPrivateKey);
+ mbedtls_rsa_set_padding(rsaContext, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA1);
+#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
+ if(data->length % rsaContext->len != 0)
+ return UA_STATUSCODE_BADINTERNALERROR;
+#else
+ size_t keylen = mbedtls_rsa_get_len(rsaContext);
+ if(data->length % keylen != 0)
+ return UA_STATUSCODE_BADINTERNALERROR;
+#endif
-static UA_StatusCode
-UA_ChannelModule_Basic256_New_Context (const UA_SecurityPolicy * securityPolicy,
- const UA_ByteString * remoteCertificate,
- void ** channelContext) {
- if (securityPolicy == NULL || remoteCertificate == NULL ||
- channelContext == NULL) {
- return UA_STATUSCODE_BADINTERNALERROR;
- }
- Channel_Context_Basic256 * context = (Channel_Context_Basic256 *)
- UA_malloc (sizeof (Channel_Context_Basic256));
- if (context == NULL) {
- return UA_STATUSCODE_BADOUTOFMEMORY;
- }
+ size_t inOffset = 0;
+ size_t outOffset = 0;
+ size_t outLength = 0;
+ unsigned char buf[512];
- UA_ByteString_init(&context->localSymSigningKey);
- UA_ByteString_init(&context->localSymEncryptingKey);
- UA_ByteString_init(&context->localSymIv);
- UA_ByteString_init(&context->remoteSymSigningKey);
- UA_ByteString_init(&context->remoteSymEncryptingKey);
- UA_ByteString_init(&context->remoteSymIv);
+ while(inOffset < data->length) {
+#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
+ int mbedErr = mbedtls_rsa_rsaes_oaep_decrypt(rsaContext, mbedtls_ctr_drbg_random,
+ drbgContext, MBEDTLS_RSA_PRIVATE,
+ NULL, 0, &outLength,
+ data->data + inOffset,
+ buf, 512);
+#else
+ int mbedErr = mbedtls_rsa_rsaes_oaep_decrypt(rsaContext, mbedtls_ctr_drbg_random,
+ drbgContext,
+ NULL, 0, &outLength,
+ data->data + inOffset,
+ buf, 512);
+#endif
- UA_StatusCode retval = UA_copyCertificate (&context->remoteCertificate,
- remoteCertificate);
- if (retval != UA_STATUSCODE_GOOD) {
- UA_free (context);
- return retval;
- }
+ if(mbedErr)
+ return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
- /* decode to X509 */
- context->remoteCertificateX509 = UA_OpenSSL_LoadCertificate(&context->remoteCertificate);
- if (context->remoteCertificateX509 == NULL) {
- UA_ByteString_clear (&context->remoteCertificate);
- UA_free (context);
- return UA_STATUSCODE_BADCERTIFICATECHAININCOMPLETE;
+ memcpy(data->data + outOffset, buf, outLength);
+#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
+ inOffset += rsaContext->len;
+#else
+ inOffset += keylen;
+#endif
+ outOffset += outLength;
}
- context->policyContext = (Policy_Context_Basic256 *)
- (securityPolicy->policyContext);
+ data->length = outOffset;
+ return UA_STATUSCODE_GOOD;
+}
- *channelContext = context;
+int
+UA_mbedTLS_LoadPrivateKey(const UA_ByteString *key, mbedtls_pk_context *target, void *p_rng) {
+ UA_ByteString data = UA_mbedTLS_CopyDataFormatAware(key);
+#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
+ int mbedErr = mbedtls_pk_parse_key(target, data.data, data.length, NULL, 0);
+#else
+ int mbedErr = mbedtls_pk_parse_key(target, data.data, data.length, NULL, 0, mbedtls_entropy_func, p_rng);
+#endif
+ UA_ByteString_clear(&data);
+ return mbedErr;
+}
- UA_LOG_INFO (securityPolicy->logger,
- UA_LOGCATEGORY_SECURITYPOLICY,
- "The basic256 security policy channel with openssl is created.");
+UA_StatusCode
+UA_mbedTLS_LoadLocalCertificate(const UA_ByteString *certData,
+ UA_ByteString *target) {
+ UA_ByteString data = UA_mbedTLS_CopyDataFormatAware(certData);
- return UA_STATUSCODE_GOOD;
-}
+ mbedtls_x509_crt cert;
+ mbedtls_x509_crt_init(&cert);
-/* delete the channel context */
+ int mbedErr = mbedtls_x509_crt_parse(&cert, data.data, data.length);
-static void
-UA_ChannelModule_Basic256_Delete_Context (void * channelContext) {
- if (channelContext != NULL) {
- Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *)
- channelContext;
- X509_free (cc->remoteCertificateX509);
- UA_ByteString_deleteMembers (&cc->remoteCertificate);
- UA_ByteString_deleteMembers (&cc->localSymSigningKey);
- UA_ByteString_deleteMembers (&cc->localSymEncryptingKey);
- UA_ByteString_deleteMembers (&cc->localSymIv);
- UA_ByteString_deleteMembers (&cc->remoteSymSigningKey);
- UA_ByteString_deleteMembers (&cc->remoteSymEncryptingKey);
- UA_ByteString_deleteMembers (&cc->remoteSymIv);
- UA_LOG_INFO (cc->policyContext->logger,
- UA_LOGCATEGORY_SECURITYPOLICY,
- "The basic256 security policy channel with openssl is deleted.");
+ UA_StatusCode result = UA_STATUSCODE_BADINVALIDARGUMENT;
- UA_free (cc);
+ if (!mbedErr) {
+ UA_ByteString tmp;
+ tmp.data = cert.raw.p;
+ tmp.length = cert.raw.len;
+
+ result = UA_ByteString_copy(&tmp, target);
+ } else {
+ UA_ByteString_init(target);
}
+
+ UA_ByteString_clear(&data);
+ mbedtls_x509_crt_free(&cert);
+ return result;
}
-/* Compares the supplied certificate with the certificate
- * in the endpoit context
- */
+// mbedTLS expects PEM data to be null terminated
+// The data length parameter must include the null terminator
+UA_ByteString
+UA_mbedTLS_CopyDataFormatAware(const UA_ByteString *data) {
+ UA_ByteString result;
+ UA_ByteString_init(&result);
-static UA_StatusCode
-UA_Asy_Basic256_compareCertificateThumbprint (const UA_SecurityPolicy * securityPolicy,
- const UA_ByteString * certificateThumbprint) {
- if (securityPolicy == NULL || certificateThumbprint == NULL) {
- return UA_STATUSCODE_BADINVALIDARGUMENT;
- }
- Policy_Context_Basic256 *pc = (Policy_Context_Basic256 *)
- securityPolicy->policyContext;
- if(!UA_ByteString_equal(certificateThumbprint, &pc->localCertThumbprint)) {
- return UA_STATUSCODE_BADCERTIFICATEINVALID;
+ if (!data->length)
+ return result;
+
+ if (data->length && data->data[0] == '-') {
+ UA_ByteString_allocBuffer(&result, data->length + 1);
+ memcpy(result.data, data->data, data->length);
+ result.data[data->length] = '\0';
+ } else {
+ UA_ByteString_copy(data, &result);
}
- return UA_STATUSCODE_GOOD;
+
+ return result;
}
-/* Generates a thumbprint for the specified certificate */
+#endif
-static UA_StatusCode
-UA_Asy_Basic256_makeCertificateThumbprint (const UA_SecurityPolicy * securityPolicy,
- const UA_ByteString * certificate,
- UA_ByteString * thumbprint) {
- return UA_Openssl_X509_GetCertificateThumbprint (certificate,
- thumbprint, false);
-}
+/**** amalgamated original file "/plugins/ua_log_stdout.c" ****/
-static UA_StatusCode
-UA_ChannelModule_Basic256_setLocalSymSigningKey (void * channelContext,
- const UA_ByteString * key) {
- if (key == NULL || channelContext == NULL) {
- return UA_STATUSCODE_BADINVALIDARGUMENT;
- }
+/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
+ * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
+ *
+ * Copyright 2016-2018 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
+ * Copyright 2017 (c) Thomas Stalder, Blue Time Concept SA
+ */
- Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *) channelContext;
- UA_ByteString_deleteMembers(&cc->localSymSigningKey);
- return UA_ByteString_copy(key, &cc->localSymSigningKey);
-}
-static UA_StatusCode
-UA_ChannelModule_Basic256_setLocalSymEncryptingKey (void * channelContext,
- const UA_ByteString * key) {
- if (key == NULL || channelContext == NULL) {
- return UA_STATUSCODE_BADINVALIDARGUMENT;
- }
+#include <stdio.h>
- Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *) channelContext;
- UA_ByteString_deleteMembers(&cc->localSymEncryptingKey);
- return UA_ByteString_copy(key, &cc->localSymEncryptingKey);
-}
+#if UA_MULTITHREADING >= 100
+#include <pthread.h>
+static pthread_mutex_t printf_mutex = PTHREAD_MUTEX_INITIALIZER;
+#endif
-static UA_StatusCode
-UA_ChannelModule_Basic256_setLocalSymIv (void * channelContext,
- const UA_ByteString * iv) {
- if (iv == NULL || channelContext == NULL) {
- return UA_STATUSCODE_BADINVALIDARGUMENT;
- }
+/* ANSI escape sequences for color output taken from here:
+ * https://stackoverflow.com/questions/3219393/stdlib-and-colored-output-in-c*/
- Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *) channelContext;
- UA_ByteString_deleteMembers(&cc->localSymIv);
- return UA_ByteString_copy(iv, &cc->localSymIv);
-}
+#ifdef UA_ENABLE_LOG_COLORS
+# define ANSI_COLOR_RED "\x1b[31m"
+# define ANSI_COLOR_GREEN "\x1b[32m"
+# define ANSI_COLOR_YELLOW "\x1b[33m"
+# define ANSI_COLOR_BLUE "\x1b[34m"
+# define ANSI_COLOR_MAGENTA "\x1b[35m"
+# define ANSI_COLOR_CYAN "\x1b[36m"
+# define ANSI_COLOR_RESET "\x1b[0m"
+#else
+# define ANSI_COLOR_RED ""
+# define ANSI_COLOR_GREEN ""
+# define ANSI_COLOR_YELLOW ""
+# define ANSI_COLOR_BLUE ""
+# define ANSI_COLOR_MAGENTA ""
+# define ANSI_COLOR_CYAN ""
+# define ANSI_COLOR_RESET ""
+#endif
-static UA_StatusCode
-UA_ChannelModule_Basic256_setRemoteSymSigningKey (void * channelContext,
- const UA_ByteString * key) {
- if (key == NULL || channelContext == NULL) {
- return UA_STATUSCODE_BADINVALIDARGUMENT;
- }
+const char *logLevelNames[6] = {"trace", "debug",
+ ANSI_COLOR_GREEN "info",
+ ANSI_COLOR_YELLOW "warn",
+ ANSI_COLOR_RED "error",
+ ANSI_COLOR_MAGENTA "fatal"};
+const char *logCategoryNames[7] = {"network", "channel", "session", "server",
+ "client", "userland", "securitypolicy"};
- Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *) channelContext;
- UA_ByteString_deleteMembers(&cc->remoteSymSigningKey);
- return UA_ByteString_copy(key, &cc->remoteSymSigningKey);
-}
+#ifdef __clang__
+__attribute__((__format__(__printf__, 4 , 0)))
+#endif
+void
+UA_Log_Stdout_log(void *context, UA_LogLevel level, UA_LogCategory category,
+ const char *msg, va_list args) {
-static UA_StatusCode
-UA_ChannelModule_Basic256_setRemoteSymEncryptingKey (void * channelContext,
- const UA_ByteString * key) {
- if (key == NULL || channelContext == NULL) {
- return UA_STATUSCODE_BADINVALIDARGUMENT;
- }
+ /* Assume that context is casted to UA_LogLevel */
+ /* TODO we may later change this to a struct with bitfields to filter on category */
+ if ( context != NULL && (UA_LogLevel)(uintptr_t)context > level )
+ return;
- Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *) channelContext;
- UA_ByteString_deleteMembers(&cc->remoteSymEncryptingKey);
- return UA_ByteString_copy(key, &cc->remoteSymEncryptingKey);
-}
+ UA_Int64 tOffset = UA_DateTime_localTimeUtcOffset();
+ UA_DateTimeStruct dts = UA_DateTime_toStruct(UA_DateTime_now() + tOffset);
-static UA_StatusCode
-UA_ChannelModule_Basic256_setRemoteSymIv (void * channelContext,
- const UA_ByteString * key) {
- if (key == NULL || channelContext == NULL) {
- return UA_STATUSCODE_BADINVALIDARGUMENT;
- }
+#if UA_MULTITHREADING >= 100
+ pthread_mutex_lock(&printf_mutex);
+#endif
- Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *) channelContext;
- UA_ByteString_deleteMembers(&cc->remoteSymIv);
- return UA_ByteString_copy(key, &cc->remoteSymIv);
+ printf("[%04u-%02u-%02u %02u:%02u:%02u.%03u (UTC%+05d)] %s/%s" ANSI_COLOR_RESET "\t",
+ dts.year, dts.month, dts.day, dts.hour, dts.min, dts.sec, dts.milliSec,
+ (int)(tOffset / UA_DATETIME_SEC / 36), logLevelNames[level], logCategoryNames[category]);
+ vprintf(msg, args);
+ printf("\n");
+ fflush(stdout);
+
+#if UA_MULTITHREADING >= 100
+ pthread_mutex_unlock(&printf_mutex);
+#endif
}
-static UA_StatusCode
-UA_ChannelModule_Basic256_compareCertificate (const void * channelContext,
- const UA_ByteString * certificate) {
- if(channelContext == NULL || certificate == NULL) {
- return UA_STATUSCODE_BADINVALIDARGUMENT;
- }
+void
+UA_Log_Stdout_clear(void *logContext) {
- const Channel_Context_Basic256 * cc =
- (const Channel_Context_Basic256 *) channelContext;
- return UA_OpenSSL_X509_compare (certificate, cc->remoteCertificateX509);
}
-static size_t
-UA_AsySig_Basic256_getRemoteSignatureSize (const UA_SecurityPolicy * securityPolicy,
- const void * channelContext) {
- if (securityPolicy == NULL || channelContext == NULL) {
- return UA_STATUSCODE_BADINVALIDARGUMENT;
- }
+const UA_Logger UA_Log_Stdout_ = {UA_Log_Stdout_log, NULL, UA_Log_Stdout_clear};
+const UA_Logger *UA_Log_Stdout = &UA_Log_Stdout_;
- const Channel_Context_Basic256 * cc = (const Channel_Context_Basic256 *) channelContext;
- UA_Int32 keyLen = 0;
- UA_Openssl_RSA_Public_GetKeyLength (cc->remoteCertificateX509, &keyLen);
- return (size_t) keyLen;
+/* By default the client and server is configured with UA_Log_Stdout
+ This constructs a logger with a configurable max log level */
+
+UA_Logger UA_Log_Stdout_withLevel(UA_LogLevel minlevel)
+{
+ UA_Logger logger = {UA_Log_Stdout_log, (void*)minlevel, UA_Log_Stdout_clear};
+ return logger;
}
-static size_t
-UA_AsySig_Basic256_getLocalSignatureSize (const UA_SecurityPolicy * securityPolicy,
- const void * channelContext) {
- if (securityPolicy == NULL || channelContext == NULL) {
- return UA_STATUSCODE_BADINVALIDARGUMENT;
- }
+/**** amalgamated original file "/plugins/ua_accesscontrol_default.c" ****/
- Policy_Context_Basic256 * pc =
- (Policy_Context_Basic256 *) securityPolicy->policyContext;
- UA_Int32 keyLen = 0;
- UA_Openssl_RSA_Private_GetKeyLength (pc->localPrivateKey, &keyLen);
+/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
+ * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
+ *
+ * Copyright 2016-2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
+ * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
+ * Copyright 2019 (c) HMS Industrial Networks AB (Author: Jonas Green)
+ */
- return (size_t) keyLen;
-}
-static UA_StatusCode
-UA_AsySig_Basic256_Verify (const UA_SecurityPolicy * securityPolicy,
- void * channelContext,
- const UA_ByteString * message,
- const UA_ByteString * signature) {
- if (securityPolicy == NULL || message == NULL || signature == NULL ||
- channelContext == NULL) {
- return UA_STATUSCODE_BADINVALIDARGUMENT;
- }
+/* Example access control management. Anonymous and username / password login.
+ * The access rights are maximally permissive.
+ *
+ * FOR PRODUCTION USE, THIS EXAMPLE PLUGIN SHOULD BE REPLACED WITH LESS
+ * PERMISSIVE ACCESS CONTROL.
+ *
+ * For TransferSubscriptions, we check whether the transfer happens between
+ * Sessions for the same user. */
- Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *) channelContext;
- UA_StatusCode retval = UA_OpenSSL_RSA_PKCS1_V15_SHA1_Verify (message,
- cc->remoteCertificateX509, signature);
+typedef struct {
+ UA_Boolean allowAnonymous;
+ size_t usernamePasswordLoginSize;
+ UA_UsernamePasswordLogin *usernamePasswordLogin;
+ UA_CertificateVerification verifyX509;
+} AccessControlContext;
- return retval;
-}
+#define ANONYMOUS_POLICY "open62541-anonymous-policy"
+#define CERTIFICATE_POLICY "open62541-certificate-policy"
+#define USERNAME_POLICY "open62541-username-policy"
+const UA_String anonymous_policy = UA_STRING_STATIC(ANONYMOUS_POLICY);
+const UA_String certificate_policy = UA_STRING_STATIC(CERTIFICATE_POLICY);
+const UA_String username_policy = UA_STRING_STATIC(USERNAME_POLICY);
+
+/************************/
+/* Access Control Logic */
+/************************/
static UA_StatusCode
-UA_AsySig_Basic256_Sign (const UA_SecurityPolicy * securityPolicy,
- void * channelContext,
- const UA_ByteString * message,
- UA_ByteString * signature) {
- if (securityPolicy == NULL || channelContext == NULL ||
- message == NULL || signature == NULL) {
- return UA_STATUSCODE_BADINVALIDARGUMENT;
- }
+activateSession_default(UA_Server *server, UA_AccessControl *ac,
+ const UA_EndpointDescription *endpointDescription,
+ const UA_ByteString *secureChannelRemoteCertificate,
+ const UA_NodeId *sessionId,
+ const UA_ExtensionObject *userIdentityToken,
+ void **sessionContext) {
+ AccessControlContext *context = (AccessControlContext*)ac->context;
- Policy_Context_Basic256 * pc =
- (Policy_Context_Basic256 *) securityPolicy->policyContext;
- return UA_Openssl_RSA_PKCS1_V15_SHA1_Sign (message, pc->localPrivateKey,
- signature);
-}
+ /* The empty token is interpreted as anonymous */
+ if(userIdentityToken->encoding == UA_EXTENSIONOBJECT_ENCODED_NOBODY) {
+ if(!context->allowAnonymous)
+ return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
-static size_t
-UA_AsymEn_Basic256_getRemotePlainTextBlockSize (const UA_SecurityPolicy * securityPolicy,
- const void * channelContext) {
- if (securityPolicy == NULL || channelContext == NULL) {
- return UA_STATUSCODE_BADINVALIDARGUMENT;
+ /* No userdata atm */
+ *sessionContext = NULL;
+ return UA_STATUSCODE_GOOD;
}
- const Channel_Context_Basic256 * cc = (const Channel_Context_Basic256 *) channelContext;
- UA_Int32 keyLen = 0;
- UA_Openssl_RSA_Public_GetKeyLength (cc->remoteCertificateX509, &keyLen);
- return (size_t) keyLen - UA_SECURITYPOLICY_BASIC256SHA1_RSAPADDING_LEN;
-}
+ /* Could the token be decoded? */
+ if(userIdentityToken->encoding < UA_EXTENSIONOBJECT_DECODED)
+ return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
-static size_t
-UA_AsymEn_Basic256_getRemoteBlockSize (const UA_SecurityPolicy * securityPolicy,
- const void * channelContext) {
- if (securityPolicy == NULL || channelContext == NULL) {
- return UA_STATUSCODE_BADINVALIDARGUMENT;
- }
+ /* Anonymous login */
+ if(userIdentityToken->content.decoded.type == &UA_TYPES[UA_TYPES_ANONYMOUSIDENTITYTOKEN]) {
+ if(!context->allowAnonymous)
+ return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
- const Channel_Context_Basic256 * cc = (const Channel_Context_Basic256 *) channelContext;
- UA_Int32 keyLen = 0;
- UA_Openssl_RSA_Public_GetKeyLength (cc->remoteCertificateX509, &keyLen);
- return (size_t) keyLen;
-}
+ const UA_AnonymousIdentityToken *token = (UA_AnonymousIdentityToken*)
+ userIdentityToken->content.decoded.data;
-static size_t
-UA_AsymEn_Basic256_getRemoteKeyLength (const UA_SecurityPolicy * securityPolicy,
- const void * channelContext) {
- if (securityPolicy == NULL || channelContext == NULL)
- return UA_STATUSCODE_BADINVALIDARGUMENT;
+ /* Compatibility notice: Siemens OPC Scout v10 provides an empty
+ * policyId. This is not compliant. For compatibility, assume that empty
+ * policyId == ANONYMOUS_POLICY */
+ if(token->policyId.data && !UA_String_equal(&token->policyId, &anonymous_policy))
+ return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
- const Channel_Context_Basic256 * cc = (const Channel_Context_Basic256 *) channelContext;
- UA_Int32 keyLen = 0;
- UA_Openssl_RSA_Public_GetKeyLength (cc->remoteCertificateX509, &keyLen);
- return (size_t) keyLen * 8;
-}
+ /* No userdata atm */
+ *sessionContext = NULL;
+ return UA_STATUSCODE_GOOD;
+ }
-static size_t
-UA_AsymEn_Basic256_getLocalKeyLength (const UA_SecurityPolicy * securityPolicy,
- const void * channelContext) {
- if (securityPolicy == NULL || channelContext == NULL)
- return UA_STATUSCODE_BADINVALIDARGUMENT;
+ /* Username and password */
+ if(userIdentityToken->content.decoded.type == &UA_TYPES[UA_TYPES_USERNAMEIDENTITYTOKEN]) {
+ const UA_UserNameIdentityToken *userToken =
+ (UA_UserNameIdentityToken*)userIdentityToken->content.decoded.data;
- Policy_Context_Basic256 * pc =
- (Policy_Context_Basic256 *) securityPolicy->policyContext;
- UA_Int32 keyLen = 0;
- UA_Openssl_RSA_Private_GetKeyLength (pc->localPrivateKey, &keyLen);
+ if(!UA_String_equal(&userToken->policyId, &username_policy))
+ return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
- return (size_t) keyLen * 8;
-}
+ /* The userToken has been decrypted by the server before forwarding
+ * it to the plugin. This information can be used here. */
+ /* if(userToken->encryptionAlgorithm.length > 0) {} */
-static UA_StatusCode
-UA_AsymEn_Basic256_Decrypt (const UA_SecurityPolicy * securityPolicy,
- void * channelContext,
- UA_ByteString * data) {
- if (securityPolicy == NULL || channelContext == NULL || data == NULL) {
- return UA_STATUSCODE_BADINVALIDARGUMENT;
- }
+ /* Empty username and password */
+ if(userToken->userName.length == 0 && userToken->password.length == 0)
+ return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
- Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *) channelContext;
- UA_StatusCode ret = UA_Openssl_RSA_Oaep_Decrypt (data,
- cc->policyContext->localPrivateKey);
- return ret;
-}
+ /* Try to match username/pw */
+ UA_Boolean match = false;
+ for(size_t i = 0; i < context->usernamePasswordLoginSize; i++) {
+ if(UA_String_equal(&userToken->userName, &context->usernamePasswordLogin[i].username) &&
+ UA_String_equal(&userToken->password, &context->usernamePasswordLogin[i].password)) {
+ match = true;
+ break;
+ }
+ }
+ if(!match)
+ return UA_STATUSCODE_BADUSERACCESSDENIED;
-static UA_StatusCode
-UA_AsymEn_Basic256_Encrypt (const UA_SecurityPolicy * securityPolicy,
- void * channelContext,
- UA_ByteString * data) {
- if (securityPolicy == NULL || channelContext == NULL ||
- data == NULL) {
- return UA_STATUSCODE_BADINVALIDARGUMENT;
+ /* For the CTT, recognize whether two sessions are */
+ UA_ByteString *username = UA_ByteString_new();
+ if(username)
+ UA_ByteString_copy(&userToken->userName, username);
+ *sessionContext = username;
+ return UA_STATUSCODE_GOOD;
}
- Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *) channelContext;
- return UA_Openssl_RSA_OAEP_Encrypt (data, UA_SECURITYPOLICY_BASIC256SHA1_RSAPADDING_LEN,
- cc->remoteCertificateX509);
-}
+ /* x509 certificate */
+ if(userIdentityToken->content.decoded.type == &UA_TYPES[UA_TYPES_X509IDENTITYTOKEN]) {
+ const UA_X509IdentityToken *userToken = (UA_X509IdentityToken*)
+ userIdentityToken->content.decoded.data;
-static UA_StatusCode
-UA_Sym_Basic256_generateNonce (const UA_SecurityPolicy * sp,
- UA_ByteString * out) {
- UA_Int32 rc = RAND_bytes(out->data, (int) out->length);
- if (rc != 1) {
- return UA_STATUSCODE_BADUNEXPECTEDERROR;
+ if(!UA_String_equal(&userToken->policyId, &certificate_policy))
+ return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
+
+ if(!context->verifyX509.verifyCertificate)
+ return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
+
+ return context->verifyX509.
+ verifyCertificate(context->verifyX509.context,
+ &userToken->certificateData);
}
- return UA_STATUSCODE_GOOD;
-}
-static UA_StatusCode
-UA_Sym_Basic256_generateKey (const UA_SecurityPolicy * securityPolicy,
- const UA_ByteString * secret,
- const UA_ByteString * seed,
- UA_ByteString * out) {
- return UA_Openssl_Random_Key_PSHA1_Derive (secret, seed, out);
+ /* Unsupported token type */
+ return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
}
-static size_t
-UA_SymEn_Basic256_getLocalKeyLength (const UA_SecurityPolicy * securityPolicy,
- const void * channelContext) {
- /* 32 bytes 256 bits */
- return UA_SECURITYPOLICY_BASIC256_SYM_ENCRYPTION_KEY_LENGTH;
+static void
+closeSession_default(UA_Server *server, UA_AccessControl *ac,
+ const UA_NodeId *sessionId, void *sessionContext) {
+ if(sessionContext)
+ UA_ByteString_delete((UA_ByteString*)sessionContext);
}
-static size_t
-UA_SymEn_Basic256_getBlockSize (const UA_SecurityPolicy * securityPolicy,
- const void * channelContext) {
- return UA_SECURITYPOLICY_BASIC256_SYM_ENCRYPTION_BLOCK_SIZE;
+static UA_UInt32
+getUserRightsMask_default(UA_Server *server, UA_AccessControl *ac,
+ const UA_NodeId *sessionId, void *sessionContext,
+ const UA_NodeId *nodeId, void *nodeContext) {
+ return 0xFFFFFFFF;
}
-static size_t
-UA_SymEn_Basic256_getRemoteKeyLength (const UA_SecurityPolicy * securityPolicy,
- const void * channelContext) {
- /* 32 bytes 256 bits */
- return UA_SECURITYPOLICY_BASIC256_SYM_ENCRYPTION_KEY_LENGTH;
+static UA_Byte
+getUserAccessLevel_default(UA_Server *server, UA_AccessControl *ac,
+ const UA_NodeId *sessionId, void *sessionContext,
+ const UA_NodeId *nodeId, void *nodeContext) {
+ return 0xFF;
}
-static size_t
-UA_SymEn_Basic256_getPlainTextBlockSize (const UA_SecurityPolicy * securityPolicy,
- const void * channelContext) {
- return UA_SECURITYPOLICY_BASIC256_SYM_PLAIN_TEXT_BLOCK_SIZE;
+static UA_Boolean
+getUserExecutable_default(UA_Server *server, UA_AccessControl *ac,
+ const UA_NodeId *sessionId, void *sessionContext,
+ const UA_NodeId *methodId, void *methodContext) {
+ return true;
}
-static UA_StatusCode
-UA_SymEn_Basic256_Encrypt (const UA_SecurityPolicy * securityPolicy,
- void * channelContext,
- UA_ByteString * data) {
- if(securityPolicy == NULL || channelContext == NULL || data == NULL)
- return UA_STATUSCODE_BADINVALIDARGUMENT;
-
- Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *) channelContext;
- return UA_OpenSSL_AES_256_CBC_Encrypt (&cc->localSymIv, &cc->localSymEncryptingKey, data);
+static UA_Boolean
+getUserExecutableOnObject_default(UA_Server *server, UA_AccessControl *ac,
+ const UA_NodeId *sessionId, void *sessionContext,
+ const UA_NodeId *methodId, void *methodContext,
+ const UA_NodeId *objectId, void *objectContext) {
+ return true;
}
-static UA_StatusCode
-UA_SymEn_Basic256_Decrypt (const UA_SecurityPolicy * securityPolicy,
- void * channelContext,
- UA_ByteString * data) {
- if(securityPolicy == NULL || channelContext == NULL || data == NULL)
- return UA_STATUSCODE_BADINVALIDARGUMENT;
- Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *) channelContext;
- return UA_OpenSSL_AES_256_CBC_Decrypt (&cc->remoteSymIv, &cc->remoteSymEncryptingKey, data);
+static UA_Boolean
+allowAddNode_default(UA_Server *server, UA_AccessControl *ac,
+ const UA_NodeId *sessionId, void *sessionContext,
+ const UA_AddNodesItem *item) {
+ return true;
}
-static size_t
-UA_SymSig_Basic256_getKeyLength (const UA_SecurityPolicy * securityPolicy,
- const void * channelContext) {
- return UA_SECURITYPOLICY_BASIC256_SYM_SIGNING_KEY_LENGTH;
+static UA_Boolean
+allowAddReference_default(UA_Server *server, UA_AccessControl *ac,
+ const UA_NodeId *sessionId, void *sessionContext,
+ const UA_AddReferencesItem *item) {
+ return true;
}
-static size_t
-UA_SymSig_Basic256_getSignatureSize (const UA_SecurityPolicy * securityPolicy,
- const void * channelContext) {
- return UA_SHA1_LENGTH;
+static UA_Boolean
+allowDeleteNode_default(UA_Server *server, UA_AccessControl *ac,
+ const UA_NodeId *sessionId, void *sessionContext,
+ const UA_DeleteNodesItem *item) {
+ return true;
}
-static UA_StatusCode
-UA_SymSig_Basic256_Verify (const UA_SecurityPolicy * securityPolicy,
- void * channelContext,
- const UA_ByteString * message,
- const UA_ByteString * signature) {
- if (securityPolicy == NULL || channelContext == NULL ||
- message == NULL || signature == NULL)
- return UA_STATUSCODE_BADINVALIDARGUMENT;
-
- Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *) channelContext;
- return UA_OpenSSL_HMAC_SHA1_Verify (message,
- &cc->remoteSymSigningKey,
- signature);
+static UA_Boolean
+allowDeleteReference_default(UA_Server *server, UA_AccessControl *ac,
+ const UA_NodeId *sessionId, void *sessionContext,
+ const UA_DeleteReferencesItem *item) {
+ return true;
}
-static UA_StatusCode
-UA_SymSig_Basic256_Sign (const UA_SecurityPolicy * securityPolicy,
- void * channelContext,
- const UA_ByteString * message,
- UA_ByteString * signature) {
- if (securityPolicy == NULL || channelContext == NULL ||
- message == NULL || signature == NULL)
- return UA_STATUSCODE_BADINVALIDARGUMENT;
-
- Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *) channelContext;
- return UA_OpenSSL_HMAC_SHA1_Sign (message, &cc->localSymSigningKey, signature);
+static UA_Boolean
+allowBrowseNode_default(UA_Server *server, UA_AccessControl *ac,
+ const UA_NodeId *sessionId, void *sessionContext,
+ const UA_NodeId *nodeId, void *nodeContext) {
+ return true;
}
-/* the main entry of Basic256 */
-
-UA_StatusCode
-UA_SecurityPolicy_Basic256 (UA_SecurityPolicy * policy,
- const UA_ByteString localCertificate,
- const UA_ByteString localPrivateKey,
- const UA_Logger * logger) {
- UA_SecurityPolicyAsymmetricModule * const asymmetricModule = &policy->asymmetricModule;
- UA_SecurityPolicySymmetricModule * const symmetricModule = &policy->symmetricModule;
- UA_SecurityPolicyChannelModule * const channelModule = &policy->channelModule;
- UA_StatusCode retval;
-
- UA_LOG_INFO (logger, UA_LOGCATEGORY_SECURITYPOLICY,
- "The basic256 security policy with openssl is added.");
-
- UA_Openssl_Init ();
- memset(policy, 0, sizeof(UA_SecurityPolicy));
- policy->logger = logger;
- policy->policyUri = UA_STRING("http://opcfoundation.org/UA/SecurityPolicy#Basic256\0");
+#ifdef UA_ENABLE_SUBSCRIPTIONS
+static UA_Boolean
+allowTransferSubscription_default(UA_Server *server, UA_AccessControl *ac,
+ const UA_NodeId *oldSessionId, void *oldSessionContext,
+ const UA_NodeId *newSessionId, void *newSessionContext) {
+ if(oldSessionContext == newSessionContext)
+ return true;
+ if(oldSessionContext && newSessionContext)
+ return UA_ByteString_equal((UA_ByteString*)oldSessionContext,
+ (UA_ByteString*)newSessionContext);
+ return false;
+}
+#endif
- /* set ChannelModule context */
+#ifdef UA_ENABLE_HISTORIZING
+static UA_Boolean
+allowHistoryUpdateUpdateData_default(UA_Server *server, UA_AccessControl *ac,
+ const UA_NodeId *sessionId, void *sessionContext,
+ const UA_NodeId *nodeId,
+ UA_PerformUpdateType performInsertReplace,
+ const UA_DataValue *value) {
+ return true;
+}
- channelModule->newContext = UA_ChannelModule_Basic256_New_Context;
- channelModule->deleteContext = UA_ChannelModule_Basic256_Delete_Context;
+static UA_Boolean
+allowHistoryUpdateDeleteRawModified_default(UA_Server *server, UA_AccessControl *ac,
+ const UA_NodeId *sessionId, void *sessionContext,
+ const UA_NodeId *nodeId,
+ UA_DateTime startTimestamp,
+ UA_DateTime endTimestamp,
+ bool isDeleteModified) {
+ return true;
+}
+#endif
- channelModule->setLocalSymSigningKey = UA_ChannelModule_Basic256_setLocalSymSigningKey;
- channelModule->setLocalSymEncryptingKey = UA_ChannelModule_Basic256_setLocalSymEncryptingKey;
- channelModule->setLocalSymIv = UA_ChannelModule_Basic256_setLocalSymIv;
- channelModule->setRemoteSymSigningKey = UA_ChannelModule_Basic256_setRemoteSymSigningKey;
- channelModule->setRemoteSymEncryptingKey = UA_ChannelModule_Basic256_setRemoteSymEncryptingKey;
- channelModule->setRemoteSymIv = UA_ChannelModule_Basic256_setRemoteSymIv;
- channelModule->compareCertificate = UA_ChannelModule_Basic256_compareCertificate;
+/***************************************/
+/* Create Delete Access Control Plugin */
+/***************************************/
- retval = UA_OpenSSL_LoadLocalCertificate(&localCertificate, &policy->localCertificate);
+static void clear_default(UA_AccessControl *ac) {
+ UA_Array_delete((void*)(uintptr_t)ac->userTokenPolicies,
+ ac->userTokenPoliciesSize,
+ &UA_TYPES[UA_TYPES_USERTOKENPOLICY]);
+ ac->userTokenPolicies = NULL;
+ ac->userTokenPoliciesSize = 0;
- if (retval != UA_STATUSCODE_GOOD)
- return retval;
+ AccessControlContext *context = (AccessControlContext*)ac->context;
- /* asymmetricModule */
+ if (context) {
+ for(size_t i = 0; i < context->usernamePasswordLoginSize; i++) {
+ UA_String_clear(&context->usernamePasswordLogin[i].username);
+ UA_String_clear(&context->usernamePasswordLogin[i].password);
+ }
+ if(context->usernamePasswordLoginSize > 0)
+ UA_free(context->usernamePasswordLogin);
- asymmetricModule->compareCertificateThumbprint = UA_Asy_Basic256_compareCertificateThumbprint;
- asymmetricModule->makeCertificateThumbprint = UA_Asy_Basic256_makeCertificateThumbprint;
+ if(context->verifyX509.clear)
+ context->verifyX509.clear(&context->verifyX509);
- /* AsymmetricModule - signature algorithm */
+ UA_free(ac->context);
+ ac->context = NULL;
+ }
+}
- UA_SecurityPolicySignatureAlgorithm * asySigAlgorithm =
- &asymmetricModule->cryptoModule.signatureAlgorithm;
- asySigAlgorithm->uri = UA_STRING("http://www.w3.org/2000/09/xmldsig#rsa-sha1\0");
- asySigAlgorithm->getRemoteSignatureSize = UA_AsySig_Basic256_getRemoteSignatureSize;
- asySigAlgorithm->getLocalSignatureSize = UA_AsySig_Basic256_getLocalSignatureSize;
- asySigAlgorithm->verify = UA_AsySig_Basic256_Verify;
- asySigAlgorithm->sign = UA_AsySig_Basic256_Sign;
- asySigAlgorithm->getLocalKeyLength = NULL;
- asySigAlgorithm->getRemoteKeyLength = NULL;
+UA_StatusCode
+UA_AccessControl_default(UA_ServerConfig *config,
+ UA_Boolean allowAnonymous,
+ UA_CertificateVerification *verifyX509,
+ const UA_ByteString *userTokenPolicyUri,
+ size_t usernamePasswordLoginSize,
+ const UA_UsernamePasswordLogin *usernamePasswordLogin) {
+ UA_LOG_WARNING(&config->logger, UA_LOGCATEGORY_SERVER,
+ "AccessControl: Unconfigured AccessControl. Users have all permissions.");
+ UA_AccessControl *ac = &config->accessControl;
- /* AsymmetricModule encryption algorithm */
+ if(ac->clear)
+ clear_default(ac);
+
+ ac->clear = clear_default;
+ ac->activateSession = activateSession_default;
+ ac->closeSession = closeSession_default;
+ ac->getUserRightsMask = getUserRightsMask_default;
+ ac->getUserAccessLevel = getUserAccessLevel_default;
+ ac->getUserExecutable = getUserExecutable_default;
+ ac->getUserExecutableOnObject = getUserExecutableOnObject_default;
+ ac->allowAddNode = allowAddNode_default;
+ ac->allowAddReference = allowAddReference_default;
+ ac->allowBrowseNode = allowBrowseNode_default;
- UA_SecurityPolicyEncryptionAlgorithm * asymEncryAlg =
- &asymmetricModule->cryptoModule.encryptionAlgorithm;
- asymEncryAlg->uri = UA_STRING("http://www.w3.org/2001/04/xmlenc#rsa-oaep\0");
- asymEncryAlg->getRemotePlainTextBlockSize = UA_AsymEn_Basic256_getRemotePlainTextBlockSize;
- asymEncryAlg->getRemoteBlockSize = UA_AsymEn_Basic256_getRemoteBlockSize;
- asymEncryAlg->getRemoteKeyLength = UA_AsymEn_Basic256_getRemoteKeyLength;
- asymEncryAlg->getLocalKeyLength = UA_AsymEn_Basic256_getLocalKeyLength;
- asymEncryAlg->getLocalPlainTextBlockSize = NULL;
- asymEncryAlg->getLocalBlockSize = NULL;
- asymEncryAlg->decrypt = UA_AsymEn_Basic256_Decrypt;
- asymEncryAlg->encrypt = UA_AsymEn_Basic256_Encrypt;
+#ifdef UA_ENABLE_SUBSCRIPTIONS
+ ac->allowTransferSubscription = allowTransferSubscription_default;
+#endif
- /* SymmetricModule */
+#ifdef UA_ENABLE_HISTORIZING
+ ac->allowHistoryUpdateUpdateData = allowHistoryUpdateUpdateData_default;
+ ac->allowHistoryUpdateDeleteRawModified = allowHistoryUpdateDeleteRawModified_default;
+#endif
- symmetricModule->secureChannelNonceLength = 32;
- symmetricModule->generateNonce = UA_Sym_Basic256_generateNonce;
- symmetricModule->generateKey = UA_Sym_Basic256_generateKey;
+ ac->allowDeleteNode = allowDeleteNode_default;
+ ac->allowDeleteReference = allowDeleteReference_default;
- /* Symmetric encryption Algorithm */
+ AccessControlContext *context = (AccessControlContext*)
+ UA_malloc(sizeof(AccessControlContext));
+ if(!context)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ memset(context, 0, sizeof(AccessControlContext));
+ ac->context = context;
- UA_SecurityPolicyEncryptionAlgorithm * symEncryptionAlgorithm =
- &symmetricModule->cryptoModule.encryptionAlgorithm;
- symEncryptionAlgorithm->uri = UA_STRING("http://www.w3.org/2001/04/xmlenc#aes256-cbc\0");
- symEncryptionAlgorithm->getLocalKeyLength = UA_SymEn_Basic256_getLocalKeyLength;
- symEncryptionAlgorithm->getLocalBlockSize = UA_SymEn_Basic256_getBlockSize;
- symEncryptionAlgorithm->getRemoteKeyLength = UA_SymEn_Basic256_getRemoteKeyLength;
- symEncryptionAlgorithm->getRemoteBlockSize = UA_SymEn_Basic256_getBlockSize;
- symEncryptionAlgorithm->getLocalPlainTextBlockSize = UA_SymEn_Basic256_getPlainTextBlockSize;
- symEncryptionAlgorithm->getRemotePlainTextBlockSize = UA_SymEn_Basic256_getPlainTextBlockSize;
- symEncryptionAlgorithm->decrypt = UA_SymEn_Basic256_Decrypt;
- symEncryptionAlgorithm->encrypt = UA_SymEn_Basic256_Encrypt;
+ /* Allow anonymous? */
+ context->allowAnonymous = allowAnonymous;
+ if(allowAnonymous) {
+ UA_LOG_INFO(&config->logger, UA_LOGCATEGORY_SERVER,
+ "AccessControl: Anonymous login is enabled");
+ }
- /* Symmetric signature Algorithm */
+ /* Allow x509 certificates? Move the plugin over. */
+ if(verifyX509) {
+ context->verifyX509 = *verifyX509;
+ memset(verifyX509, 0, sizeof(UA_CertificateVerification));
+ } else {
+ memset(&context->verifyX509, 0, sizeof(UA_CertificateVerification));
+ UA_LOG_INFO(&config->logger, UA_LOGCATEGORY_SERVER,
+ "AccessControl: x509 certificate user authentication is enabled");
+ }
- UA_SecurityPolicySignatureAlgorithm * symSignatureAlgorithm =
- &symmetricModule->cryptoModule.signatureAlgorithm;
- symSignatureAlgorithm->uri = UA_STRING("http://www.w3.org/2000/09/xmldsig#hmac-sha1\0");
- symSignatureAlgorithm->getLocalKeyLength = UA_SymSig_Basic256_getKeyLength;
- symSignatureAlgorithm->getRemoteKeyLength = UA_SymSig_Basic256_getKeyLength;
- symSignatureAlgorithm->getRemoteSignatureSize = UA_SymSig_Basic256_getSignatureSize;
- symSignatureAlgorithm->getLocalSignatureSize = UA_SymSig_Basic256_getSignatureSize;
- symSignatureAlgorithm->verify = UA_SymSig_Basic256_Verify;
- symSignatureAlgorithm->sign = UA_SymSig_Basic256_Sign;
+ /* Copy username/password to the access control plugin */
+ if(usernamePasswordLoginSize > 0) {
+ context->usernamePasswordLogin = (UA_UsernamePasswordLogin*)
+ UA_malloc(usernamePasswordLoginSize * sizeof(UA_UsernamePasswordLogin));
+ if(!context->usernamePasswordLogin)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ context->usernamePasswordLoginSize = usernamePasswordLoginSize;
+ for(size_t i = 0; i < usernamePasswordLoginSize; i++) {
+ UA_String_copy(&usernamePasswordLogin[i].username,
+ &context->usernamePasswordLogin[i].username);
+ UA_String_copy(&usernamePasswordLogin[i].password,
+ &context->usernamePasswordLogin[i].password);
+ }
+ }
- /* set the policy context */
+ /* Set the allowed policies */
+ size_t policies = 0;
+ if(allowAnonymous)
+ policies++;
+ if(verifyX509)
+ policies++;
+ if(usernamePasswordLoginSize > 0)
+ policies++;
+ ac->userTokenPoliciesSize = 0;
+ ac->userTokenPolicies = (UA_UserTokenPolicy *)
+ UA_Array_new(policies, &UA_TYPES[UA_TYPES_USERTOKENPOLICY]);
+ if(!ac->userTokenPolicies)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ ac->userTokenPoliciesSize = policies;
- retval = UA_Policy_Basic256_New_Context (policy, localPrivateKey, logger);
- if (retval != UA_STATUSCODE_GOOD) {
- UA_ByteString_clear (&policy->localCertificate);
- return retval;
+ policies = 0;
+ if(allowAnonymous) {
+ ac->userTokenPolicies[policies].tokenType = UA_USERTOKENTYPE_ANONYMOUS;
+ ac->userTokenPolicies[policies].policyId = UA_STRING_ALLOC(ANONYMOUS_POLICY);
+ policies++;
}
- policy->clear = UA_Policy_Basic256_Clear_Context;
- /* Use the same signature algorithm as the asymmetric component for
- certificate signing (see standard) */
- policy->certificateSigningAlgorithm = policy->asymmetricModule.cryptoModule.signatureAlgorithm;
+ if(verifyX509) {
+ ac->userTokenPolicies[policies].tokenType = UA_USERTOKENTYPE_CERTIFICATE;
+ ac->userTokenPolicies[policies].policyId = UA_STRING_ALLOC(CERTIFICATE_POLICY);
+#if UA_LOGLEVEL <= 400
+ if(UA_ByteString_equal(userTokenPolicyUri, &UA_SECURITY_POLICY_NONE_URI)) {
+ UA_LOG_WARNING(&config->logger, UA_LOGCATEGORY_SERVER,
+ "x509 Certificate Authentication configured, "
+ "but no encrypting SecurityPolicy. "
+ "This can leak credentials on the network.");
+ }
+#endif
+ UA_ByteString_copy(userTokenPolicyUri,
+ &ac->userTokenPolicies[policies].securityPolicyUri);
+ policies++;
+ }
+ if(usernamePasswordLoginSize > 0) {
+ ac->userTokenPolicies[policies].tokenType = UA_USERTOKENTYPE_USERNAME;
+ ac->userTokenPolicies[policies].policyId = UA_STRING_ALLOC(USERNAME_POLICY);
+#if UA_LOGLEVEL <= 400
+ if(UA_ByteString_equal(userTokenPolicyUri, &UA_SECURITY_POLICY_NONE_URI)) {
+ UA_LOG_WARNING(&config->logger, UA_LOGCATEGORY_SERVER,
+ "Username/Password Authentication configured, "
+ "but no encrypting SecurityPolicy. "
+ "This can leak credentials on the network.");
+ }
+#endif
+ UA_ByteString_copy(userTokenPolicyUri,
+ &ac->userTokenPolicies[policies].securityPolicyUri);
+ }
return UA_STATUSCODE_GOOD;
}
-#endif
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/plugins/securityPolicies/openssl/ua_openssl_basic256sha256.c" ***********************************/
+/**** amalgamated original file "/plugins/ua_nodestore_ziptree.c" ****/
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
+ * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
*
- * Copyright 2020 (c) Wind River Systems, Inc.
- * Copyright 2020 (c) basysKom GmbH
+ * Copyright 2014-2018 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
+ * Copyright 2017 (c) Julian Grothoff
+ * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
*/
-/*
-modification history
---------------------
-01feb20,lan written
-*/
+#ifndef container_of
+#define container_of(ptr, type, member) \
+ (type *)((uintptr_t)ptr - offsetof(type,member))
+#endif
-#ifdef UA_ENABLE_ENCRYPTION_OPENSSL
+struct NodeEntry;
+typedef struct NodeEntry NodeEntry;
+struct NodeEntry {
+ ZIP_ENTRY(NodeEntry) zipfields;
+ UA_UInt32 nodeIdHash;
+ UA_UInt16 refCount; /* How many consumers have a reference to the node? */
+ UA_Boolean deleted; /* Node was marked as deleted and can be deleted when refCount == 0 */
+ NodeEntry *orig; /* If a copy is made to replace a node, track that we
+ * replace only the node from which the copy was made.
+ * Important for concurrent operations. */
+ UA_NodeId nodeId; /* This is actually a UA_Node that also starts with a NodeId */
+};
-#include <openssl/hmac.h>
-#include <openssl/sha.h>
-#include <openssl/rsa.h>
-#include <openssl/x509.h>
-#include <openssl/rand.h>
-#include <openssl/rsa.h>
+/* Absolute ordering for NodeIds */
+static enum ZIP_CMP
+cmpNodeId(const void *a, const void *b) {
+ const NodeEntry *aa = (const NodeEntry*)a;
+ const NodeEntry *bb = (const NodeEntry*)b;
-#define UA_SHA256_LENGTH 32 /* 256 bit */
-#define UA_SECURITYPOLICY_BASIC256SHA256_RSAPADDING_LEN 42
-#define UA_SECURITYPOLICY_BASIC256SHA256_SYM_SIGNING_KEY_LENGTH 32
-#define UA_SECURITYPOLICY_BASIC256SHA256_SYM_ENCRYPTION_KEY_LENGTH 32
-#define UA_SECURITYPOLICY_BASIC256SHA256_SYM_ENCRYPTION_BLOCK_SIZE 16
-#define UA_SECURITYPOLICY_BASIC256SHA256_SYM_PLAIN_TEXT_BLOCK_SIZE 16
-#define UA_SECURITYPOLICY_BASIC256SHA256_MINASYMKEYLENGTH 256
-#define UA_SECURITYPOLICY_BASIC256SHA256_MAXASYMKEYLENGTH 512
+ /* Compare hash */
+ if(aa->nodeIdHash < bb->nodeIdHash)
+ return ZIP_CMP_LESS;
+ if(aa->nodeIdHash > bb->nodeIdHash)
+ return ZIP_CMP_MORE;
-typedef struct {
- EVP_PKEY * localPrivateKey;
- UA_ByteString localCertThumbprint;
- const UA_Logger * logger;
-} Policy_Context_Basic256Sha256;
+ /* Compore nodes in detail */
+ return (enum ZIP_CMP)UA_NodeId_order(&aa->nodeId, &bb->nodeId);
+}
+
+ZIP_HEAD(NodeTree, NodeEntry);
+typedef struct NodeTree NodeTree;
typedef struct {
- UA_ByteString localSymSigningKey;
- UA_ByteString localSymEncryptingKey;
- UA_ByteString localSymIv;
- UA_ByteString remoteSymSigningKey;
- UA_ByteString remoteSymEncryptingKey;
- UA_ByteString remoteSymIv;
+ NodeTree root;
- Policy_Context_Basic256Sha256 * policyContext;
- UA_ByteString remoteCertificate;
- X509 * remoteCertificateX509; /* X509 */
-} Channel_Context_Basic256Sha256;
+ /* Maps ReferenceTypeIndex to the NodeId of the ReferenceType */
+ UA_NodeId referenceTypeIds[UA_REFERENCETYPESET_MAX];
+ UA_Byte referenceTypeCounter;
+} ZipContext;
-/* create the policy context */
+ZIP_FUNCTIONS(NodeTree, NodeEntry, zipfields, NodeEntry, zipfields, cmpNodeId)
-static UA_StatusCode
-UA_Policy_New_Context (UA_SecurityPolicy * securityPolicy,
- const UA_ByteString localPrivateKey,
- const UA_Logger * logger) {
- Policy_Context_Basic256Sha256 * context = (Policy_Context_Basic256Sha256 *)
- UA_malloc (sizeof (Policy_Context_Basic256Sha256));
- if (context == NULL) {
- return UA_STATUSCODE_BADOUTOFMEMORY;
+static NodeEntry *
+newEntry(UA_NodeClass nodeClass) {
+ size_t size = sizeof(NodeEntry) - sizeof(UA_NodeId);
+ switch(nodeClass) {
+ case UA_NODECLASS_OBJECT:
+ size += sizeof(UA_ObjectNode);
+ break;
+ case UA_NODECLASS_VARIABLE:
+ size += sizeof(UA_VariableNode);
+ break;
+ case UA_NODECLASS_METHOD:
+ size += sizeof(UA_MethodNode);
+ break;
+ case UA_NODECLASS_OBJECTTYPE:
+ size += sizeof(UA_ObjectTypeNode);
+ break;
+ case UA_NODECLASS_VARIABLETYPE:
+ size += sizeof(UA_VariableTypeNode);
+ break;
+ case UA_NODECLASS_REFERENCETYPE:
+ size += sizeof(UA_ReferenceTypeNode);
+ break;
+ case UA_NODECLASS_DATATYPE:
+ size += sizeof(UA_DataTypeNode);
+ break;
+ case UA_NODECLASS_VIEW:
+ size += sizeof(UA_ViewNode);
+ break;
+ default:
+ return NULL;
}
-
- context->localPrivateKey = UA_OpenSSL_LoadPrivateKey(&localPrivateKey);
+ NodeEntry *entry = (NodeEntry*)UA_calloc(1, size);
+ if(!entry)
+ return NULL;
+ UA_Node *node = (UA_Node*)&entry->nodeId;
+ node->head.nodeClass = nodeClass;
+ return entry;
+}
- if (!context->localPrivateKey) {
- UA_free (context);
- return UA_STATUSCODE_BADINVALIDARGUMENT;
- }
+static void
+deleteEntry(NodeEntry *entry) {
+ UA_Node_clear((UA_Node*)&entry->nodeId);
+ UA_free(entry);
+}
- UA_StatusCode retval = UA_Openssl_X509_GetCertificateThumbprint (
- &securityPolicy->localCertificate,
- &context->localCertThumbprint, true
- );
- if (retval != UA_STATUSCODE_GOOD) {
- EVP_PKEY_free(context->localPrivateKey);
- UA_free (context);
- return retval;
+static void
+cleanupEntry(NodeEntry *entry) {
+ if(entry->refCount > 0)
+ return;
+ if(entry->deleted) {
+ deleteEntry(entry);
+ return;
}
+ UA_NodeHead *head = (UA_NodeHead*)&entry->nodeId;
+ for(size_t i = 0; i < head->referencesSize; i++) {
+ UA_NodeReferenceKind *rk = &head->references[i];
+ if(rk->targetsSize > 16 && !rk->hasRefTree)
+ UA_NodeReferenceKind_switch(rk);
+ }
+}
- context->logger = logger;
- securityPolicy->policyContext = context;
+/***********************/
+/* Interface functions */
+/***********************/
- return UA_STATUSCODE_GOOD;
+/* Not yet inserted into the ZipContext */
+static UA_Node *
+zipNsNewNode(void *nsCtx, UA_NodeClass nodeClass) {
+ NodeEntry *entry = newEntry(nodeClass);
+ if(!entry)
+ return NULL;
+ return (UA_Node*)&entry->nodeId;
}
-/* clear the policy context */
-
+/* Not yet inserted into the ZipContext */
static void
-UA_Policy_Clear_Context (UA_SecurityPolicy *policy) {
- if (policy == NULL)
- return;
-
- UA_ByteString_deleteMembers(&policy->localCertificate);
+zipNsDeleteNode(void *nsCtx, UA_Node *node) {
+ deleteEntry(container_of(node, NodeEntry, nodeId));
+}
- /* delete all allocated members in the context */
+static const UA_Node *
+zipNsGetNode(void *nsCtx, const UA_NodeId *nodeId) {
+ ZipContext *ns = (ZipContext*)nsCtx;
+ NodeEntry dummy;
+ dummy.nodeIdHash = UA_NodeId_hash(nodeId);
+ dummy.nodeId = *nodeId;
+ NodeEntry *entry = ZIP_FIND(NodeTree, &ns->root, &dummy);
+ if(!entry)
+ return NULL;
+ ++entry->refCount;
+ return (const UA_Node*)&entry->nodeId;
+}
- Policy_Context_Basic256Sha256 * pc = (Policy_Context_Basic256Sha256 *)
- policy->policyContext;
- EVP_PKEY_free(pc->localPrivateKey);
- UA_ByteString_deleteMembers (&pc->localCertThumbprint);
- UA_free (pc);
- return;
+static void
+zipNsReleaseNode(void *nsCtx, const UA_Node *node) {
+ if(!node)
+ return;
+ NodeEntry *entry = container_of(node, NodeEntry, nodeId);
+ UA_assert(entry->refCount > 0);
+ --entry->refCount;
+ cleanupEntry(entry);
}
-/* create the channel context */
+static UA_StatusCode
+zipNsGetNodeCopy(void *nsCtx, const UA_NodeId *nodeId,
+ UA_Node **outNode) {
+ /* Find the node */
+ const UA_Node *node = zipNsGetNode(nsCtx, nodeId);
+ if(!node)
+ return UA_STATUSCODE_BADNODEIDUNKNOWN;
-static UA_StatusCode
-UA_ChannelModule_New_Context (const UA_SecurityPolicy * securityPolicy,
- const UA_ByteString * remoteCertificate,
- void ** channelContext) {
- if (securityPolicy == NULL || remoteCertificate == NULL ||
- channelContext == NULL) {
- return UA_STATUSCODE_BADINTERNALERROR;
- }
- Channel_Context_Basic256Sha256 * context = (Channel_Context_Basic256Sha256 *)
- UA_malloc (sizeof (Channel_Context_Basic256Sha256));
- if (context == NULL) {
+ /* Create the new entry */
+ NodeEntry *ne = newEntry(node->head.nodeClass);
+ if(!ne) {
+ zipNsReleaseNode(nsCtx, node);
return UA_STATUSCODE_BADOUTOFMEMORY;
}
- UA_ByteString_init(&context->localSymSigningKey);
- UA_ByteString_init(&context->localSymEncryptingKey);
- UA_ByteString_init(&context->localSymIv);
- UA_ByteString_init(&context->remoteSymSigningKey);
- UA_ByteString_init(&context->remoteSymEncryptingKey);
- UA_ByteString_init(&context->remoteSymIv);
-
- UA_StatusCode retval = UA_copyCertificate (&context->remoteCertificate,
- remoteCertificate);
- if (retval != UA_STATUSCODE_GOOD) {
- UA_free (context);
+ /* Copy the node content */
+ UA_Node *nnode = (UA_Node*)&ne->nodeId;
+ UA_StatusCode retval = UA_Node_copy(node, nnode);
+ zipNsReleaseNode(nsCtx, node);
+ if(retval != UA_STATUSCODE_GOOD) {
+ deleteEntry(ne);
return retval;
}
- /* decode to X509 */
- context->remoteCertificateX509 = UA_OpenSSL_LoadCertificate(&context->remoteCertificate);
- if (context->remoteCertificateX509 == NULL) {
- UA_ByteString_clear (&context->remoteCertificate);
- UA_free (context);
- }
+ ne->orig = container_of(node, NodeEntry, nodeId);
+ *outNode = nnode;
+ return UA_STATUSCODE_GOOD;
+}
- context->policyContext = (Policy_Context_Basic256Sha256 *)
- (securityPolicy->policyContext);
+static UA_StatusCode
+zipNsInsertNode(void *nsCtx, UA_Node *node, UA_NodeId *addedNodeId) {
+ NodeEntry *entry = container_of(node, NodeEntry, nodeId);
+ ZipContext *ns = (ZipContext*)nsCtx;
- *channelContext = context;
+ /* Ensure that the NodeId is unique */
+ NodeEntry dummy;
+ memset(&dummy, 0, sizeof(NodeEntry));
+ dummy.nodeId = node->head.nodeId;
+ if(node->head.nodeId.identifierType == UA_NODEIDTYPE_NUMERIC &&
+ node->head.nodeId.identifier.numeric == 0) {
+ do { /* Create a random nodeid until we find an unoccupied id */
+ UA_UInt32 numId = UA_UInt32_random();
+#if SIZE_MAX <= UA_UINT32_MAX
+ /* The compressed "immediate" representation of nodes does not
+ * support the full range on 32bit systems. Generate smaller
+ * identifiers as they can be stored more compactly. */
+ if(numId >= (0x01 << 24))
+ numId = numId % (0x01 << 24);
+#endif
+ node->head.nodeId.identifier.numeric = numId;
+ dummy.nodeId.identifier.numeric = numId;
+ dummy.nodeIdHash = UA_NodeId_hash(&node->head.nodeId);
+ } while(ZIP_FIND(NodeTree, &ns->root, &dummy));
+ } else {
+ dummy.nodeIdHash = UA_NodeId_hash(&node->head.nodeId);
+ if(ZIP_FIND(NodeTree, &ns->root, &dummy)) { /* The nodeid exists */
+ deleteEntry(entry);
+ return UA_STATUSCODE_BADNODEIDEXISTS;
+ }
+ }
- UA_LOG_INFO (securityPolicy->logger,
- UA_LOGCATEGORY_SECURITYPOLICY,
- "The basic256sha256 security policy channel with openssl is created.");
+ /* Copy the NodeId */
+ if(addedNodeId) {
+ UA_StatusCode retval = UA_NodeId_copy(&node->head.nodeId, addedNodeId);
+ if(retval != UA_STATUSCODE_GOOD) {
+ deleteEntry(entry);
+ return retval;
+ }
+ }
- return UA_STATUSCODE_GOOD;
-}
+ /* For new ReferencetypeNodes add to the index map */
+ if(node->head.nodeClass == UA_NODECLASS_REFERENCETYPE) {
+ UA_ReferenceTypeNode *refNode = &node->referenceTypeNode;
+ if(ns->referenceTypeCounter >= UA_REFERENCETYPESET_MAX) {
+ deleteEntry(entry);
+ return UA_STATUSCODE_BADINTERNALERROR;
+ }
-/* delete the channel context */
+ UA_StatusCode retval =
+ UA_NodeId_copy(&node->head.nodeId, &ns->referenceTypeIds[ns->referenceTypeCounter]);
+ if(retval != UA_STATUSCODE_GOOD) {
+ deleteEntry(entry);
+ return UA_STATUSCODE_BADINTERNALERROR;
+ }
-static void
-UA_ChannelModule_Delete_Context (void * channelContext) {
- if (channelContext != NULL) {
- Channel_Context_Basic256Sha256 * cc = (Channel_Context_Basic256Sha256 *)
- channelContext;
- X509_free (cc->remoteCertificateX509);
- UA_ByteString_deleteMembers (&cc->remoteCertificate);
- UA_ByteString_deleteMembers (&cc->localSymSigningKey);
- UA_ByteString_deleteMembers (&cc->localSymEncryptingKey);
- UA_ByteString_deleteMembers (&cc->localSymIv);
- UA_ByteString_deleteMembers (&cc->remoteSymSigningKey);
- UA_ByteString_deleteMembers (&cc->remoteSymEncryptingKey);
- UA_ByteString_deleteMembers (&cc->remoteSymIv);
+ /* Assign the ReferenceTypeIndex to the new ReferenceTypeNode */
+ refNode->referenceTypeIndex = ns->referenceTypeCounter;
+ refNode->subTypes = UA_REFTYPESET(ns->referenceTypeCounter);
- UA_LOG_INFO (cc->policyContext->logger,
- UA_LOGCATEGORY_SECURITYPOLICY,
- "The basic256sha256 security policy channel with openssl is deleted.");
- UA_free (cc);
+ ns->referenceTypeCounter++;
}
+
+ /* Insert the node */
+ entry->nodeIdHash = dummy.nodeIdHash;
+ ZIP_INSERT(NodeTree, &ns->root, entry, UA_UInt32_random());
+ return UA_STATUSCODE_GOOD;
}
-/* Verifies the signature of the message using the provided keys in the context.
- * AsymmetricSignatureAlgorithm_RSA-PKCS15-SHA2-256
- */
+static UA_StatusCode
+zipNsReplaceNode(void *nsCtx, UA_Node *node) {
+ /* Find the node */
+ const UA_Node *oldNode = zipNsGetNode(nsCtx, &node->head.nodeId);
+ if(!oldNode) {
+ deleteEntry(container_of(node, NodeEntry, nodeId));
+ return UA_STATUSCODE_BADNODEIDUNKNOWN;
+ }
-static UA_StatusCode
-UA_AsySig_Basic256Sha256_Verify (const UA_SecurityPolicy * securityPolicy,
- void * channelContext,
- const UA_ByteString * message,
- const UA_ByteString * signature) {
- if (securityPolicy == NULL || message == NULL || signature == NULL ||
- channelContext == NULL) {
+ /* Test if the copy is current */
+ NodeEntry *entry = container_of(node, NodeEntry, nodeId);
+ NodeEntry *oldEntry = container_of(oldNode, NodeEntry, nodeId);
+ if(oldEntry != entry->orig) {
+ /* The node was already updated since the copy was made */
+ deleteEntry(entry);
+ zipNsReleaseNode(nsCtx, oldNode);
return UA_STATUSCODE_BADINTERNALERROR;
- }
+ }
- Channel_Context_Basic256Sha256 * cc = (Channel_Context_Basic256Sha256 *)
- channelContext;
- UA_StatusCode retval = UA_OpenSSL_RSA_PKCS1_V15_SHA256_Verify (message,
- cc->remoteCertificateX509, signature);
+ /* Replace */
+ ZipContext *ns = (ZipContext*)nsCtx;
+ ZIP_REMOVE(NodeTree, &ns->root, oldEntry);
+ entry->nodeIdHash = oldEntry->nodeIdHash;
+ ZIP_INSERT(NodeTree, &ns->root, entry, ZIP_RANK(entry, zipfields));
+ oldEntry->deleted = true;
- return retval;
+ zipNsReleaseNode(nsCtx, oldNode);
+ return UA_STATUSCODE_GOOD;
}
-/* Compares the supplied certificate with the certificate
- * in the endpoit context
- */
-
static UA_StatusCode
-UA_compareCertificateThumbprint (const UA_SecurityPolicy * securityPolicy,
- const UA_ByteString * certificateThumbprint) {
- if (securityPolicy == NULL || certificateThumbprint == NULL) {
- return UA_STATUSCODE_BADINVALIDARGUMENT;
- }
- Policy_Context_Basic256Sha256 *pc = (Policy_Context_Basic256Sha256 *)
- securityPolicy->policyContext;
- if(!UA_ByteString_equal(certificateThumbprint, &pc->localCertThumbprint))
- return UA_STATUSCODE_BADCERTIFICATEINVALID;
+zipNsRemoveNode(void *nsCtx, const UA_NodeId *nodeId) {
+ ZipContext *ns = (ZipContext*)nsCtx;
+ NodeEntry dummy;
+ dummy.nodeIdHash = UA_NodeId_hash(nodeId);
+ dummy.nodeId = *nodeId;
+ NodeEntry *entry = ZIP_FIND(NodeTree, &ns->root, &dummy);
+ if(!entry)
+ return UA_STATUSCODE_BADNODEIDUNKNOWN;
+ ZIP_REMOVE(NodeTree, &ns->root, entry);
+ entry->deleted = true;
+ cleanupEntry(entry);
return UA_STATUSCODE_GOOD;
}
-/* Generates a thumbprint for the specified certificate */
-
-static UA_StatusCode
-UA_makeCertificateThumbprint (const UA_SecurityPolicy * securityPolicy,
- const UA_ByteString * certificate,
- UA_ByteString * thumbprint) {
- return UA_Openssl_X509_GetCertificateThumbprint (certificate,
- thumbprint, false);
+static const UA_NodeId *
+zipNsGetReferenceTypeId(void *nsCtx, UA_Byte refTypeIndex) {
+ ZipContext *ns = (ZipContext*)nsCtx;
+ if(refTypeIndex >= ns->referenceTypeCounter)
+ return NULL;
+ return &ns->referenceTypeIds[refTypeIndex];
}
-static UA_StatusCode
-UA_Asym_Basic256Sha256_Decrypt (const UA_SecurityPolicy *securityPolicy,
- void * channelContext,
- UA_ByteString * data) {
- if (securityPolicy == NULL || channelContext == NULL || data == NULL)
- return UA_STATUSCODE_BADINVALIDARGUMENT;
+struct VisitorData {
+ UA_NodestoreVisitor visitor;
+ void *visitorContext;
+};
- Channel_Context_Basic256Sha256 * cc = (Channel_Context_Basic256Sha256 *)
- channelContext;
- UA_StatusCode ret = UA_Openssl_RSA_Oaep_Decrypt (data,
- cc->policyContext->localPrivateKey);
- return ret;
+static void
+nodeVisitor(NodeEntry *entry, void *data) {
+ struct VisitorData *d = (struct VisitorData*)data;
+ d->visitor(d->visitorContext, (UA_Node*)&entry->nodeId);
}
-static size_t
-UA_Asym_Basic256Sha256_getRemoteSignatureSize (
- const UA_SecurityPolicy * securityPolicy,
- const void * channelContext) {
- if (securityPolicy == NULL || channelContext == NULL)
- return UA_STATUSCODE_BADINTERNALERROR;
+static void
+zipNsIterate(void *nsCtx, UA_NodestoreVisitor visitor,
+ void *visitorCtx) {
+ struct VisitorData d;
+ d.visitor = visitor;
+ d.visitorContext = visitorCtx;
+ ZipContext *ns = (ZipContext*)nsCtx;
+ ZIP_ITER(NodeTree, &ns->root, nodeVisitor, &d);
+}
- const Channel_Context_Basic256Sha256 * cc = (const Channel_Context_Basic256Sha256 *) channelContext;
- UA_Int32 keyLen = 0;
- UA_Openssl_RSA_Public_GetKeyLength (cc->remoteCertificateX509, &keyLen);
- UA_assert (keyLen == 256); /* 256 bytes 2048 bit */
- return (size_t) keyLen;
+static void
+deleteNodeVisitor(NodeEntry *entry, void *data) {
+ deleteEntry(entry);
}
-static size_t
-UA_AsySig_Basic256Sha256_getLocalSignatureSize (const UA_SecurityPolicy *securityPolicy,
- const void *channelContext) {
- if (securityPolicy == NULL || channelContext == NULL)
- return UA_STATUSCODE_BADINTERNALERROR;
+/***********************/
+/* Nodestore Lifecycle */
+/***********************/
- Policy_Context_Basic256Sha256 * pc =
- (Policy_Context_Basic256Sha256 *) securityPolicy->policyContext;
- UA_Int32 keyLen = 0;
- UA_Openssl_RSA_Private_GetKeyLength (pc->localPrivateKey, &keyLen);
- UA_assert (keyLen == 256); /* 256 bytes 2048 bits */
+static void
+zipNsClear(void *nsCtx) {
+ if (!nsCtx)
+ return;
+ ZipContext *ns = (ZipContext*)nsCtx;
+ ZIP_ITER(NodeTree, &ns->root, deleteNodeVisitor, NULL);
- return (size_t) keyLen;
+ /* Clean up the ReferenceTypes index array */
+ for(size_t i = 0; i < ns->referenceTypeCounter; i++)
+ UA_NodeId_clear(&ns->referenceTypeIds[i]);
+
+ UA_free(ns);
}
-static size_t
-UA_AsymEn_Basic256Sha256_getRemotePlainTextBlockSize (const UA_SecurityPolicy *securityPolicy,
- const void *channelContext) {
- if (securityPolicy == NULL || channelContext == NULL)
- return UA_STATUSCODE_BADINTERNALERROR;
+UA_StatusCode
+UA_Nodestore_ZipTree(UA_Nodestore *ns) {
+ /* Allocate and initialize the context */
+ ZipContext *ctx = (ZipContext*)UA_malloc(sizeof(ZipContext));
+ if(!ctx)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
- const Channel_Context_Basic256Sha256 * cc = (const Channel_Context_Basic256Sha256 *) channelContext;
- UA_Int32 keyLen = 0;
- UA_Openssl_RSA_Public_GetKeyLength (cc->remoteCertificateX509, &keyLen);
- return (size_t) keyLen - UA_SECURITYPOLICY_BASIC256SHA256_RSAPADDING_LEN;
+ ZIP_INIT(&ctx->root);
+ ctx->referenceTypeCounter = 0;
+
+ /* Populate the nodestore */
+ ns->context = (void*)ctx;
+ ns->clear = zipNsClear;
+ ns->newNode = zipNsNewNode;
+ ns->deleteNode = zipNsDeleteNode;
+ ns->getNode = zipNsGetNode;
+ ns->releaseNode = zipNsReleaseNode;
+ ns->getNodeCopy = zipNsGetNodeCopy;
+ ns->insertNode = zipNsInsertNode;
+ ns->replaceNode = zipNsReplaceNode;
+ ns->removeNode = zipNsRemoveNode;
+ ns->getReferenceTypeId = zipNsGetReferenceTypeId;
+ ns->iterate = zipNsIterate;
+
+ return UA_STATUSCODE_GOOD;
}
-static size_t
-UA_AsymEn_Basic256Sha256_getRemoteBlockSize (const UA_SecurityPolicy *securityPolicy,
- const void *channelContext) {
- if (securityPolicy == NULL || channelContext == NULL)
- return UA_STATUSCODE_BADINTERNALERROR;
+/**** amalgamated original file "/plugins/ua_nodestore_hashmap.c" ****/
- const Channel_Context_Basic256Sha256 * cc = (const Channel_Context_Basic256Sha256 *) channelContext;
- UA_Int32 keyLen = 0;
- UA_Openssl_RSA_Public_GetKeyLength (cc->remoteCertificateX509, &keyLen);
- return (size_t) keyLen;
-}
+/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
+ * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
+ *
+ * Copyright 2014-2019 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
+ * Copyright 2017 (c) Julian Grothoff
+ * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
+ */
-static size_t
-UA_AsymEn_Basic256Sha256_getRemoteKeyLength (const UA_SecurityPolicy *securityPolicy,
- const void *channelContext) {
- if (securityPolicy == NULL || channelContext == NULL)
- return UA_STATUSCODE_BADINTERNALERROR;
- const Channel_Context_Basic256Sha256 * cc = (const Channel_Context_Basic256Sha256 *) channelContext;
- UA_Int32 keyLen = 0;
- UA_Openssl_RSA_Public_GetKeyLength (cc->remoteCertificateX509, &keyLen);
- return (size_t) keyLen * 8;
-}
+#ifndef container_of
+#define container_of(ptr, type, member) \
+ (type *)((uintptr_t)ptr - offsetof(type,member))
+#endif
-static UA_StatusCode
-UA_Sym_Basic256Sha256_generateNonce (const UA_SecurityPolicy * sp,
- UA_ByteString * out) {
- UA_Int32 rc = RAND_bytes(out->data, (int) out->length);
- if (rc != 1) {
- return UA_STATUSCODE_BADUNEXPECTEDERROR;
+/* The default Nodestore is simply a hash-map from NodeIds to Nodes. To find an
+ * entry, iterate over candidate positions according to the NodeId hash.
+ *
+ * - Tombstone or non-matching NodeId: continue searching
+ * - Matching NodeId: Return the entry
+ * - NULL: Abort the search */
+
+typedef struct UA_NodeMapEntry {
+ struct UA_NodeMapEntry *orig; /* the version this is a copy from (or NULL) */
+ UA_UInt16 refCount; /* How many consumers have a reference to the node? */
+ UA_Boolean deleted; /* Node was marked as deleted and can be deleted when refCount == 0 */
+ UA_Node node;
+} UA_NodeMapEntry;
+
+#define UA_NODEMAP_MINSIZE 64
+#define UA_NODEMAP_TOMBSTONE ((UA_NodeMapEntry*)0x01)
+
+typedef struct {
+ UA_NodeMapEntry *entry;
+ UA_UInt32 nodeIdHash;
+} UA_NodeMapSlot;
+
+typedef struct {
+ UA_NodeMapSlot *slots;
+ UA_UInt32 size;
+ UA_UInt32 count;
+ UA_UInt32 sizePrimeIndex;
+
+ /* Maps ReferenceTypeIndex to the NodeId of the ReferenceType */
+ UA_NodeId referenceTypeIds[UA_REFERENCETYPESET_MAX];
+ UA_Byte referenceTypeCounter;
+} UA_NodeMap;
+
+/*********************/
+/* HashMap Utilities */
+/*********************/
+
+/* The size of the hash-map is always a prime number. They are chosen to be
+ * close to the next power of 2. So the size ca. doubles with each prime. */
+static UA_UInt32 const primes[] = {
+ 7, 13, 31, 61, 127, 251,
+ 509, 1021, 2039, 4093, 8191, 16381,
+ 32749, 65521, 131071, 262139, 524287, 1048573,
+ 2097143, 4194301, 8388593, 16777213, 33554393, 67108859,
+ 134217689, 268435399, 536870909, 1073741789, 2147483647, 4294967291
+};
+
+static UA_UInt32 mod(UA_UInt32 h, UA_UInt32 size) { return h % size; }
+static UA_UInt32 mod2(UA_UInt32 h, UA_UInt32 size) { return 1 + (h % (size - 2)); }
+
+static UA_UInt16
+higher_prime_index(UA_UInt32 n) {
+ UA_UInt16 low = 0;
+ UA_UInt16 high = (UA_UInt16)(sizeof(primes) / sizeof(UA_UInt32));
+ while(low != high) {
+ UA_UInt16 mid = (UA_UInt16)(low + ((high - low) / 2));
+ if(n > primes[mid])
+ low = (UA_UInt16)(mid + 1);
+ else
+ high = mid;
}
- return UA_STATUSCODE_GOOD;
+ return low;
}
-static size_t
-UA_SymEn_Basic256Sha256_getLocalKeyLength (const UA_SecurityPolicy *securityPolicy,
- const void *channelContext) {
- /* 32 bytes 256 bits */
- return UA_SECURITYPOLICY_BASIC256SHA256_SYM_ENCRYPTION_KEY_LENGTH;
-}
+/* Returns an empty slot or null if the nodeid exists or if no empty slot is found. */
+static UA_NodeMapSlot *
+findFreeSlot(const UA_NodeMap *ns, const UA_NodeId *nodeid) {
+ UA_UInt32 h = UA_NodeId_hash(nodeid);
+ UA_UInt32 size = ns->size;
+ UA_UInt64 idx = mod(h, size); /* Use 64bit container to avoid overflow */
+ UA_UInt32 startIdx = (UA_UInt32)idx;
+ UA_UInt32 hash2 = mod2(h, size);
-static size_t
-UA_SymEn_Basic256Sha256_getLocalBlockSize (
- const UA_SecurityPolicy *securityPolicy,
- const void *channelContext) {
- return UA_SECURITYPOLICY_BASIC256SHA256_SYM_ENCRYPTION_BLOCK_SIZE;
-}
+ UA_NodeMapSlot *candidate = NULL;
+ do {
+ UA_NodeMapSlot *slot = &ns->slots[(UA_UInt32)idx];
-static size_t
-UA_SymSig_Basic256Sha256_getLocalKeyLength (const UA_SecurityPolicy * securityPolicy,
- const void * channelContext) {
- /* 32 bytes 256 bits */
- return UA_SECURITYPOLICY_BASIC256SHA256_SYM_SIGNING_KEY_LENGTH;
+ if(slot->entry > UA_NODEMAP_TOMBSTONE) {
+ /* A Node with the NodeId does already exist */
+ if(slot->nodeIdHash == h &&
+ UA_NodeId_equal(&slot->entry->node.head.nodeId, nodeid))
+ return NULL;
+ } else {
+ /* Found a candidate node */
+ if(!candidate)
+ candidate = slot;
+ /* No matching node can come afterwards */
+ if(slot->entry == NULL)
+ return candidate;
+ }
+
+ idx += hash2;
+ if(idx >= size)
+ idx -= size;
+ } while((UA_UInt32)idx != startIdx);
+
+ return candidate;
}
+/* The occupancy of the table after the call will be about 50% */
static UA_StatusCode
-UA_Sym_Basic256Sha256_generateKey (const UA_SecurityPolicy * securityPolicy,
- const UA_ByteString * secret,
- const UA_ByteString * seed,
- UA_ByteString * out) {
- return UA_Openssl_Random_Key_PSHA256_Derive (secret, seed, out);
+expand(UA_NodeMap *ns) {
+ UA_UInt32 osize = ns->size;
+ UA_UInt32 count = ns->count;
+ /* Resize only when table after removal of unused elements is either too
+ full or too empty */
+ if(count * 2 < osize && (count * 8 > osize || osize <= UA_NODEMAP_MINSIZE))
+ return UA_STATUSCODE_GOOD;
+
+ UA_NodeMapSlot *oslots = ns->slots;
+ UA_UInt32 nindex = higher_prime_index(count * 2);
+ UA_UInt32 nsize = primes[nindex];
+ UA_NodeMapSlot *nslots= (UA_NodeMapSlot*)UA_calloc(nsize, sizeof(UA_NodeMapSlot));
+ if(!nslots)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+
+ ns->slots = nslots;
+ ns->size = nsize;
+ ns->sizePrimeIndex = nindex;
+
+ /* recompute the position of every entry and insert the pointer */
+ for(size_t i = 0, j = 0; i < osize && j < count; ++i) {
+ if(oslots[i].entry <= UA_NODEMAP_TOMBSTONE)
+ continue;
+ UA_NodeMapSlot *s = findFreeSlot(ns, &oslots[i].entry->node.head.nodeId);
+ UA_assert(s);
+ *s = oslots[i];
+ ++j;
+ }
+
+ UA_free(oslots);
+ return UA_STATUSCODE_GOOD;
}
-static UA_StatusCode
-UA_ChannelModule_Basic256Sha256_setLocalSymSigningKey (void * channelContext,
- const UA_ByteString * key) {
- if (key == NULL || channelContext == NULL)
- return UA_STATUSCODE_BADINTERNALERROR;
- Channel_Context_Basic256Sha256 * cc = (Channel_Context_Basic256Sha256 *) channelContext;
- UA_ByteString_deleteMembers(&cc->localSymSigningKey);
- return UA_ByteString_copy(key, &cc->localSymSigningKey);
+static UA_NodeMapEntry *
+createEntry(UA_NodeClass nodeClass) {
+ size_t size = sizeof(UA_NodeMapEntry) - sizeof(UA_Node);
+ switch(nodeClass) {
+ case UA_NODECLASS_OBJECT:
+ size += sizeof(UA_ObjectNode);
+ break;
+ case UA_NODECLASS_VARIABLE:
+ size += sizeof(UA_VariableNode);
+ break;
+ case UA_NODECLASS_METHOD:
+ size += sizeof(UA_MethodNode);
+ break;
+ case UA_NODECLASS_OBJECTTYPE:
+ size += sizeof(UA_ObjectTypeNode);
+ break;
+ case UA_NODECLASS_VARIABLETYPE:
+ size += sizeof(UA_VariableTypeNode);
+ break;
+ case UA_NODECLASS_REFERENCETYPE:
+ size += sizeof(UA_ReferenceTypeNode);
+ break;
+ case UA_NODECLASS_DATATYPE:
+ size += sizeof(UA_DataTypeNode);
+ break;
+ case UA_NODECLASS_VIEW:
+ size += sizeof(UA_ViewNode);
+ break;
+ default:
+ return NULL;
+ }
+ UA_NodeMapEntry *entry = (UA_NodeMapEntry*)UA_calloc(1, size);
+ if(!entry)
+ return NULL;
+ entry->node.head.nodeClass = nodeClass;
+ return entry;
}
-static UA_StatusCode
-UA_ChannelM_Basic256Sha256_setLocalSymEncryptingKey (void * channelContext,
- const UA_ByteString * key) {
- if (key == NULL || channelContext == NULL)
- return UA_STATUSCODE_BADINTERNALERROR;
- Channel_Context_Basic256Sha256 * cc = (Channel_Context_Basic256Sha256 *) channelContext;
- UA_ByteString_deleteMembers(&cc->localSymEncryptingKey);
- return UA_ByteString_copy(key, &cc->localSymEncryptingKey);
+static void
+deleteNodeMapEntry(UA_NodeMapEntry *entry) {
+ UA_Node_clear(&entry->node);
+ UA_free(entry);
}
-static UA_StatusCode
-UA_ChannelM_Basic256Sha256_setLocalSymIv (void * channelContext,
- const UA_ByteString * iv) {
- if (iv == NULL || channelContext == NULL)
- return UA_STATUSCODE_BADINTERNALERROR;
- Channel_Context_Basic256Sha256 * cc = (Channel_Context_Basic256Sha256 *) channelContext;
- UA_ByteString_deleteMembers(&cc->localSymIv);
- return UA_ByteString_copy(iv, &cc->localSymIv);
+static void
+cleanupNodeMapEntry(UA_NodeMapEntry *entry) {
+ if(entry->refCount > 0)
+ return;
+ if(entry->deleted) {
+ deleteNodeMapEntry(entry);
+ return;
+ }
+ for(size_t i = 0; i < entry->node.head.referencesSize; i++) {
+ UA_NodeReferenceKind *rk = &entry->node.head.references[i];
+ if(rk->targetsSize > 16 && !rk->hasRefTree)
+ UA_NodeReferenceKind_switch(rk);
+ }
}
-static size_t
-UA_SymEn_Basic256Sha256_getRemoteKeyLength (const UA_SecurityPolicy * securityPolicy,
- const void * channelContext) {
- /* 32 bytes 256 bits */
- return UA_SECURITYPOLICY_BASIC256SHA256_SYM_ENCRYPTION_KEY_LENGTH;
+static UA_NodeMapSlot *
+findOccupiedSlot(const UA_NodeMap *ns, const UA_NodeId *nodeid) {
+ UA_UInt32 h = UA_NodeId_hash(nodeid);
+ UA_UInt32 size = ns->size;
+ UA_UInt64 idx = mod(h, size); /* Use 64bit container to avoid overflow */
+ UA_UInt32 hash2 = mod2(h, size);
+ UA_UInt32 startIdx = (UA_UInt32)idx;
+
+ do {
+ UA_NodeMapSlot *slot= &ns->slots[(UA_UInt32)idx];
+ if(slot->entry > UA_NODEMAP_TOMBSTONE) {
+ if(slot->nodeIdHash == h &&
+ UA_NodeId_equal(&slot->entry->node.head.nodeId, nodeid))
+ return slot;
+ } else {
+ if(slot->entry == NULL)
+ return NULL; /* No further entry possible */
+ }
+
+ idx += hash2;
+ if(idx >= size)
+ idx -= size;
+ } while((UA_UInt32)idx != startIdx);
+
+ return NULL;
}
-static size_t
-UA_SymEn_Basic256Sha256_getRemoteBlockSize (const UA_SecurityPolicy *securityPolicy,
- const void *channelContext) {
- return UA_SECURITYPOLICY_BASIC256SHA256_SYM_ENCRYPTION_BLOCK_SIZE;
+/***********************/
+/* Interface functions */
+/***********************/
+
+static UA_Node *
+UA_NodeMap_newNode(void *context, UA_NodeClass nodeClass) {
+ UA_NodeMapEntry *entry = createEntry(nodeClass);
+ if(!entry)
+ return NULL;
+ return &entry->node;
}
-static size_t
-UA_SymSig_Basic256Sha256_getRemoteKeyLength (const UA_SecurityPolicy * securityPolicy,
- const void * channelContext) {
- /* 32 bytes 256 bits */
- return UA_SECURITYPOLICY_BASIC256SHA256_SYM_SIGNING_KEY_LENGTH;
+static void
+UA_NodeMap_deleteNode(void *context, UA_Node *node) {
+ UA_NodeMapEntry *entry = container_of(node, UA_NodeMapEntry, node);
+ UA_assert(&entry->node == node);
+ deleteNodeMapEntry(entry);
}
-static UA_StatusCode
-UA_ChannelM_Basic256Sha256_setRemoteSymSigningKey (void *channelContext,
- const UA_ByteString * key) {
- if (key == NULL || channelContext == NULL)
- return UA_STATUSCODE_BADINTERNALERROR;
- Channel_Context_Basic256Sha256 * cc = (Channel_Context_Basic256Sha256 *) channelContext;
- UA_ByteString_deleteMembers(&cc->remoteSymSigningKey);
- return UA_ByteString_copy(key, &cc->remoteSymSigningKey);
+static const UA_Node *
+UA_NodeMap_getNode(void *context, const UA_NodeId *nodeid) {
+ UA_NodeMap *ns = (UA_NodeMap*)context;
+ UA_NodeMapSlot *slot = findOccupiedSlot(ns, nodeid);
+ if(!slot)
+ return NULL;
+ ++slot->entry->refCount;
+ return &slot->entry->node;
}
-static UA_StatusCode
-UA_ChannelM_Basic256Sha256_setRemoteSymEncryptingKey (void *channelContext,
- const UA_ByteString * key) {
- if (key == NULL || channelContext == NULL)
- return UA_STATUSCODE_BADINTERNALERROR;
- Channel_Context_Basic256Sha256 * cc = (Channel_Context_Basic256Sha256 *) channelContext;
- UA_ByteString_deleteMembers(&cc->remoteSymEncryptingKey);
- return UA_ByteString_copy(key, &cc->remoteSymEncryptingKey);
+static void
+UA_NodeMap_releaseNode(void *context, const UA_Node *node) {
+ if (!node)
+ return;
+ UA_NodeMapEntry *entry = container_of(node, UA_NodeMapEntry, node);
+ UA_assert(&entry->node == node);
+ UA_assert(entry->refCount > 0);
+ --entry->refCount;
+ cleanupNodeMapEntry(entry);
}
static UA_StatusCode
-UA_ChannelM_Basic256Sha256_setRemoteSymIv (void *channelContext,
- const UA_ByteString * key) {
- if (key == NULL || channelContext == NULL)
- return UA_STATUSCODE_BADINTERNALERROR;
- Channel_Context_Basic256Sha256 * cc = (Channel_Context_Basic256Sha256 *) channelContext;
- UA_ByteString_deleteMembers(&cc->remoteSymIv);
- return UA_ByteString_copy(key, &cc->remoteSymIv);
+UA_NodeMap_getNodeCopy(void *context, const UA_NodeId *nodeid,
+ UA_Node **outNode) {
+ UA_NodeMap *ns = (UA_NodeMap*)context;
+ UA_NodeMapSlot *slot = findOccupiedSlot(ns, nodeid);
+ if(!slot)
+ return UA_STATUSCODE_BADNODEIDUNKNOWN;
+ UA_NodeMapEntry *entry = slot->entry;
+ UA_NodeMapEntry *newItem = createEntry(entry->node.head.nodeClass);
+ if(!newItem)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ UA_StatusCode retval = UA_Node_copy(&entry->node, &newItem->node);
+ if(retval == UA_STATUSCODE_GOOD) {
+ newItem->orig = entry; /* Store the pointer to the original */
+ *outNode = &newItem->node;
+ } else {
+ deleteNodeMapEntry(newItem);
+ }
+ return retval;
}
static UA_StatusCode
-UA_AsySig_Basic256Sha256_sign (const UA_SecurityPolicy * securityPolicy,
- void * channelContext,
- const UA_ByteString * message,
- UA_ByteString * signature) {
- if (securityPolicy == NULL || channelContext == NULL ||
- message == NULL || signature == NULL)
- return UA_STATUSCODE_BADINTERNALERROR;
- Policy_Context_Basic256Sha256 * pc =
- (Policy_Context_Basic256Sha256 *) securityPolicy->policyContext;
- return UA_Openssl_RSA_PKCS1_V15_SHA256_Sign (message, pc->localPrivateKey,
- signature);
+UA_NodeMap_removeNode(void *context, const UA_NodeId *nodeid) {
+ UA_NodeMap *ns = (UA_NodeMap*)context;
+ UA_NodeMapSlot *slot = findOccupiedSlot(ns, nodeid);
+ if(!slot)
+ return UA_STATUSCODE_BADNODEIDUNKNOWN;
+
+ UA_NodeMapEntry *entry = slot->entry;
+ slot->entry = UA_NODEMAP_TOMBSTONE;
+ UA_atomic_sync(); /* Set the tombstone before cleaning up. E.g. if the
+ * nodestore is accessed from an interrupt. */
+ entry->deleted = true;
+ cleanupNodeMapEntry(entry);
+ --ns->count;
+ /* Downsize the hashmap if it is very empty */
+ if(ns->count * 8 < ns->size && ns->size > UA_NODEMAP_MINSIZE)
+ expand(ns); /* Can fail. Just continue with the bigger hashmap. */
+ return UA_STATUSCODE_GOOD;
}
+/*
+ * If this function fails in any way, the node parameter is deleted here,
+ * so the caller function does not need to take care of it anymore
+ */
static UA_StatusCode
-UA_AsymEn_Basic256Sha256_encrypt (const UA_SecurityPolicy * securityPolicy,
- void * channelContext,
- UA_ByteString * data) {
- if (securityPolicy == NULL || channelContext == NULL ||
- data == NULL)
- return UA_STATUSCODE_BADINTERNALERROR;
- Channel_Context_Basic256Sha256 * cc = (Channel_Context_Basic256Sha256 *) channelContext;
- return UA_Openssl_RSA_OAEP_Encrypt (data, UA_SECURITYPOLICY_BASIC256SHA256_RSAPADDING_LEN,
- cc->remoteCertificateX509);
-}
+UA_NodeMap_insertNode(void *context, UA_Node *node,
+ UA_NodeId *addedNodeId) {
+ UA_NodeMap *ns = (UA_NodeMap*)context;
+ if(ns->size * 3 <= ns->count * 4) {
+ if(expand(ns) != UA_STATUSCODE_GOOD){
+ deleteNodeMapEntry(container_of(node, UA_NodeMapEntry, node));
+ return UA_STATUSCODE_BADINTERNALERROR;
+ }
+ }
-static size_t
-UA_SymSig_Basic256Sha256_getRemoteSignatureSize (const UA_SecurityPolicy *securityPolicy,
- const void *channelContext) {
- return UA_SHA256_LENGTH;
+ UA_NodeMapSlot *slot;
+ if(node->head.nodeId.identifierType == UA_NODEIDTYPE_NUMERIC &&
+ node->head.nodeId.identifier.numeric == 0) {
+ /* Create a random nodeid: Start at least with 50,000 to make sure we
+ * don not conflict with nodes from the spec. If we find a conflict, we
+ * just try another identifier until we have tried all possible
+ * identifiers. Since the size is prime and we don't change the increase
+ * val, we will reach the starting id again. E.g. adding a nodeset will
+ * create children while there are still other nodes which need to be
+ * created. Thus the node ids may collide. */
+ UA_UInt32 size = ns->size;
+ UA_UInt64 identifier = mod(50000 + size+1, UA_UINT32_MAX); /* Use 64bit to
+ * avoid overflow */
+ UA_UInt32 increase = mod2(ns->count+1, size);
+ UA_UInt32 startId = (UA_UInt32)identifier; /* mod ensures us that the id
+ * is a valid 32 bit integer */
+
+ do {
+ node->head.nodeId.identifier.numeric = (UA_UInt32)identifier;
+ slot = findFreeSlot(ns, &node->head.nodeId);
+ if(slot)
+ break;
+ identifier += increase;
+ if(identifier >= size)
+ identifier -= size;
+#if SIZE_MAX <= UA_UINT32_MAX
+ /* The compressed "immediate" representation of nodes does not
+ * support the full range on 32bit systems. Generate smaller
+ * identifiers as they can be stored more compactly. */
+ if(identifier >= (0x01 << 24))
+ identifier = identifier % (0x01 << 24);
+#endif
+ } while((UA_UInt32)identifier != startId);
+ } else {
+ slot = findFreeSlot(ns, &node->head.nodeId);
+ }
+
+ if(!slot) {
+ deleteNodeMapEntry(container_of(node, UA_NodeMapEntry, node));
+ return UA_STATUSCODE_BADNODEIDEXISTS;
+ }
+
+ /* Copy the NodeId */
+ UA_StatusCode retval = UA_STATUSCODE_GOOD;
+ if(addedNodeId) {
+ retval = UA_NodeId_copy(&node->head.nodeId, addedNodeId);
+ if(retval != UA_STATUSCODE_GOOD) {
+ deleteNodeMapEntry(container_of(node, UA_NodeMapEntry, node));
+ return retval;
+ }
+ }
+
+ /* For new ReferencetypeNodes add to the index map */
+ if(node->head.nodeClass == UA_NODECLASS_REFERENCETYPE) {
+ UA_ReferenceTypeNode *refNode = &node->referenceTypeNode;
+ if(ns->referenceTypeCounter >= UA_REFERENCETYPESET_MAX) {
+ deleteNodeMapEntry(container_of(node, UA_NodeMapEntry, node));
+ return UA_STATUSCODE_BADINTERNALERROR;
+ }
+
+ retval = UA_NodeId_copy(&node->head.nodeId, &ns->referenceTypeIds[ns->referenceTypeCounter]);
+ if(retval != UA_STATUSCODE_GOOD) {
+ deleteNodeMapEntry(container_of(node, UA_NodeMapEntry, node));
+ return UA_STATUSCODE_BADINTERNALERROR;
+ }
+
+ /* Assign the ReferenceTypeIndex to the new ReferenceTypeNode */
+ refNode->referenceTypeIndex = ns->referenceTypeCounter;
+ refNode->subTypes = UA_REFTYPESET(ns->referenceTypeCounter);
+
+ ns->referenceTypeCounter++;
+ }
+
+ /* Insert the node */
+ UA_NodeMapEntry *newEntry = container_of(node, UA_NodeMapEntry, node);
+ slot->nodeIdHash = UA_NodeId_hash(&node->head.nodeId);
+ UA_atomic_sync(); /* Set the hash first */
+ slot->entry = newEntry;
+ ++ns->count;
+ return retval;
}
static UA_StatusCode
-UA_SymSig_Basic256Sha256_verify (const UA_SecurityPolicy * securityPolicy,
- void * channelContext,
- const UA_ByteString * message,
- const UA_ByteString * signature) {
- if (securityPolicy == NULL || channelContext == NULL ||
- message == NULL || signature == NULL)
- return UA_STATUSCODE_BADINTERNALERROR;
-
- Channel_Context_Basic256Sha256 * cc = (Channel_Context_Basic256Sha256 *) channelContext;
- return UA_OpenSSL_HMAC_SHA256_Verify (message,
- &cc->remoteSymSigningKey,
- signature);
-}
+UA_NodeMap_replaceNode(void *context, UA_Node *node) {
+ UA_NodeMap *ns = (UA_NodeMap*)context;
+ UA_NodeMapEntry *newEntry = container_of(node, UA_NodeMapEntry, node);
-static UA_StatusCode
-UA_SymSig_Basic256Sha256_sign (const UA_SecurityPolicy * securityPolicy,
- void * channelContext,
- const UA_ByteString * message,
- UA_ByteString * signature) {
- if (securityPolicy == NULL || channelContext == NULL ||
- message == NULL || signature == NULL)
+ /* Find the node */
+ UA_NodeMapSlot *slot = findOccupiedSlot(ns, &node->head.nodeId);
+ if(!slot) {
+ deleteNodeMapEntry(newEntry);
+ return UA_STATUSCODE_BADNODEIDUNKNOWN;
+ }
+
+ /* The node was already updated since the copy was made? */
+ UA_NodeMapEntry *oldEntry = slot->entry;
+ if(oldEntry != newEntry->orig) {
+ deleteNodeMapEntry(newEntry);
return UA_STATUSCODE_BADINTERNALERROR;
-
- Channel_Context_Basic256Sha256 * cc = (Channel_Context_Basic256Sha256 *) channelContext;
- return UA_OpenSSL_HMAC_SHA256_Sign (message, &cc->localSymSigningKey, signature);
+ }
+
+ /* Replace the entry */
+ slot->entry = newEntry;
+ UA_atomic_sync();
+ oldEntry->deleted = true;
+ cleanupNodeMapEntry(oldEntry);
+ return UA_STATUSCODE_GOOD;
}
-static size_t
-UA_SymSig_Basic256Sha256_getLocalSignatureSize (const UA_SecurityPolicy * securityPolicy,
- const void * channelContext) {
- return UA_SHA256_LENGTH;
+static const UA_NodeId *
+UA_NodeMap_getReferenceTypeId(void *nsCtx, UA_Byte refTypeIndex) {
+ UA_NodeMap *ns = (UA_NodeMap*)nsCtx;
+ if(refTypeIndex >= ns->referenceTypeCounter)
+ return NULL;
+ return &ns->referenceTypeIds[refTypeIndex];
}
-static UA_StatusCode
-UA_SymEn_Basic256Sha256_decrypt (const UA_SecurityPolicy * securityPolicy,
- void * channelContext,
- UA_ByteString * data) {
- if(securityPolicy == NULL || channelContext == NULL || data == NULL)
- return UA_STATUSCODE_BADINTERNALERROR;
- Channel_Context_Basic256Sha256 * cc = (Channel_Context_Basic256Sha256 *) channelContext;
- return UA_OpenSSL_AES_256_CBC_Decrypt (&cc->remoteSymIv, &cc->remoteSymEncryptingKey, data);
+static void
+UA_NodeMap_iterate(void *context, UA_NodestoreVisitor visitor,
+ void *visitorContext) {
+ UA_NodeMap *ns = (UA_NodeMap*)context;
+ for(UA_UInt32 i = 0; i < ns->size; ++i) {
+ UA_NodeMapSlot *slot = &ns->slots[i];
+ if(slot->entry > UA_NODEMAP_TOMBSTONE) {
+ /* The visitor can delete the node. So refcount here. */
+ slot->entry->refCount++;
+ visitor(visitorContext, &slot->entry->node);
+ slot->entry->refCount--;
+ cleanupNodeMapEntry(slot->entry);
+ }
+ }
}
-static UA_StatusCode
-UA_SymEn_Basic256Sha256_encrypt (const UA_SecurityPolicy * securityPolicy,
- void * channelContext,
- UA_ByteString * data) {
- if(securityPolicy == NULL || channelContext == NULL || data == NULL)
- return UA_STATUSCODE_BADINTERNALERROR;
-
- Channel_Context_Basic256Sha256 * cc = (Channel_Context_Basic256Sha256 *) channelContext;
- return UA_OpenSSL_AES_256_CBC_Encrypt (&cc->localSymIv, &cc->localSymEncryptingKey, data);
+static void
+UA_NodeMap_delete(void *context) {
+ /* Already cleaned up? */
+ if(!context)
+ return;
+
+ UA_NodeMap *ns = (UA_NodeMap*)context;
+ UA_UInt32 size = ns->size;
+ UA_NodeMapSlot *slots = ns->slots;
+ for(UA_UInt32 i = 0; i < size; ++i) {
+ if(slots[i].entry > UA_NODEMAP_TOMBSTONE) {
+ /* On debugging builds, check that all nodes were release */
+ UA_assert(slots[i].entry->refCount == 0);
+ /* Delete the node */
+ deleteNodeMapEntry(slots[i].entry);
+ }
+ }
+ UA_free(ns->slots);
+
+ /* Clean up the ReferenceTypes index array */
+ for(size_t i = 0; i < ns->referenceTypeCounter; i++)
+ UA_NodeId_clear(&ns->referenceTypeIds[i]);
+
+ UA_free(ns);
}
-static UA_StatusCode
-UA_ChannelM_Basic256Sha256_compareCertificate (const void *channelContext,
- const UA_ByteString *certificate) {
- if(channelContext == NULL || certificate == NULL)
- return UA_STATUSCODE_BADINTERNALERROR;
-
- const Channel_Context_Basic256Sha256 * cc =
- (const Channel_Context_Basic256Sha256 *) channelContext;
- return UA_OpenSSL_X509_compare (certificate, cc->remoteCertificateX509);
+UA_StatusCode
+UA_Nodestore_HashMap(UA_Nodestore *ns) {
+ /* Allocate and initialize the nodemap */
+ UA_NodeMap *nodemap = (UA_NodeMap*)UA_malloc(sizeof(UA_NodeMap));
+ if(!nodemap)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ nodemap->sizePrimeIndex = higher_prime_index(UA_NODEMAP_MINSIZE);
+ nodemap->size = primes[nodemap->sizePrimeIndex];
+ nodemap->count = 0;
+ nodemap->slots = (UA_NodeMapSlot*)
+ UA_calloc(nodemap->size, sizeof(UA_NodeMapSlot));
+ if(!nodemap->slots) {
+ UA_free(nodemap);
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ }
+
+ nodemap->referenceTypeCounter = 0;
+
+ /* Populate the nodestore */
+ ns->context = nodemap;
+ ns->clear = UA_NodeMap_delete;
+ ns->newNode = UA_NodeMap_newNode;
+ ns->deleteNode = UA_NodeMap_deleteNode;
+ ns->getNode = UA_NodeMap_getNode;
+ ns->releaseNode = UA_NodeMap_releaseNode;
+ ns->getNodeCopy = UA_NodeMap_getNodeCopy;
+ ns->insertNode = UA_NodeMap_insertNode;
+ ns->replaceNode = UA_NodeMap_replaceNode;
+ ns->removeNode = UA_NodeMap_removeNode;
+ ns->getReferenceTypeId = UA_NodeMap_getReferenceTypeId;
+ ns->iterate = UA_NodeMap_iterate;
+ return UA_STATUSCODE_GOOD;
}
-static size_t
-UA_SymEn_Basic256Sha256_getLocalPlainTextBlockSize (const UA_SecurityPolicy * securityPolicy,
- const void * channelContext) {
- return UA_SECURITYPOLICY_BASIC256SHA256_SYM_PLAIN_TEXT_BLOCK_SIZE;
+/**** amalgamated original file "/plugins/ua_config_default.c" ****/
+
+/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
+ * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
+ *
+ * Copyright 2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
+ * Copyright 2017 (c) Julian Grothoff
+ * Copyright 2017-2018 (c) Mark Giraud, Fraunhofer IOSB
+ * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
+ * Copyright 2017 (c) Thomas Stalder, Blue Time Concept SA
+ * Copyright 2018 (c) Daniel Feist, Precitec GmbH & Co. KG
+ * Copyright 2018 (c) Fabian Arndt, Root-Core
+ * Copyright 2019 (c) Kalycito Infotech Private Limited
+ * Copyright 2017-2020 (c) HMS Industrial Networks AB (Author: Jonas Green)
+ * Copyright 2020 (c) Wind River Systems, Inc.
+ */
+
+#ifdef UA_ENABLE_WEBSOCKET_SERVER
+#endif
+
+/* Struct initialization works across ANSI C/C99/C++ if it is done when the
+ * variable is first declared. Assigning values to existing structs is
+ * heterogeneous across the three. */
+static UA_INLINE UA_UInt32Range
+UA_UINT32RANGE(UA_UInt32 min, UA_UInt32 max) {
+ UA_UInt32Range range = {min, max};
+ return range;
}
-static size_t
-UA_AsymEn_Basic256Sha256_getLocalKeyLength (const UA_SecurityPolicy * securityPolicy,
- const void * channelContext) {
- if (securityPolicy == NULL || channelContext == NULL)
- return UA_STATUSCODE_BADINTERNALERROR;
+static UA_INLINE UA_DurationRange
+UA_DURATIONRANGE(UA_Duration min, UA_Duration max) {
+ UA_DurationRange range = {min, max};
+ return range;
+}
- Policy_Context_Basic256Sha256 * pc =
- (Policy_Context_Basic256Sha256 *) securityPolicy->policyContext;
- UA_Int32 keyLen = 0;
- UA_Openssl_RSA_Private_GetKeyLength (pc->localPrivateKey, &keyLen);
- UA_assert (keyLen == 256); /* 256 bytes 2048 bits */
+UA_Server *
+UA_Server_new(void) {
+ UA_ServerConfig config;
+ memset(&config, 0, sizeof(UA_ServerConfig));
+ /* Set a default logger and NodeStore for the initialization */
+ config.logger = UA_Log_Stdout_;
+ if(UA_STATUSCODE_GOOD != UA_Nodestore_HashMap(&config.nodestore)) {
+ return NULL;
+ }
- return (size_t) keyLen * 8;
+ return UA_Server_newWithConfig(&config);
}
-/* the main entry of Basic256Sha256 */
+/*******************************/
+/* Default Connection Settings */
+/*******************************/
-UA_StatusCode
-UA_SecurityPolicy_Basic256Sha256(UA_SecurityPolicy * policy,
- const UA_ByteString localCertificate,
- const UA_ByteString localPrivateKey,
- const UA_Logger * logger) {
+const UA_ConnectionConfig UA_ConnectionConfig_default = {
+ 0, /* .protocolVersion */
+ 2 << 16, /* .sendBufferSize, 64k per chunk */
+ 2 << 16, /* .recvBufferSize, 64k per chunk */
+ 2 << 29, /* .localMaxMessageSize, 512 MB */
+ 2 << 29, /* .remoteMaxMessageSize, 512 MB */
+ 2 << 14, /* .localMaxChunkCount, 16k */
+ 2 << 14 /* .remoteMaxChunkCount, 16k */
+};
- UA_SecurityPolicyAsymmetricModule * const asymmetricModule = &policy->asymmetricModule;
- UA_SecurityPolicySymmetricModule * const symmetricModule = &policy->symmetricModule;
- UA_SecurityPolicyChannelModule * const channelModule = &policy->channelModule;
- UA_StatusCode retval;
+/***************************/
+/* Default Server Settings */
+/***************************/
- UA_LOG_INFO (logger, UA_LOGCATEGORY_SECURITYPOLICY,
- "The basic256sha256 security policy with openssl is added.");
+#define MANUFACTURER_NAME "open62541"
+#define PRODUCT_NAME "open62541 OPC UA Server"
+#define PRODUCT_URI "http://open62541.org"
+#define APPLICATION_NAME "open62541-based OPC UA Application"
+#define APPLICATION_URI "urn:unconfigured:application"
+#define APPLICATION_URI_SERVER "urn:open62541.server.application"
- UA_Openssl_Init ();
- memset(policy, 0, sizeof(UA_SecurityPolicy));
- policy->logger = logger;
- policy->policyUri = UA_STRING("http://opcfoundation.org/UA/SecurityPolicy#Basic256Sha256\0");
+#define STRINGIFY(arg) #arg
+#define VERSION(MAJOR, MINOR, PATCH, LABEL) \
+ STRINGIFY(MAJOR) "." STRINGIFY(MINOR) "." STRINGIFY(PATCH) LABEL
- /* set ChannelModule context */
+static UA_StatusCode
+createEndpoint(UA_ServerConfig *conf, UA_EndpointDescription *endpoint,
+ const UA_SecurityPolicy *securityPolicy,
+ UA_MessageSecurityMode securityMode) {
+ UA_EndpointDescription_init(endpoint);
- channelModule->newContext = UA_ChannelModule_New_Context;
- channelModule->deleteContext = UA_ChannelModule_Delete_Context;
- channelModule->setLocalSymSigningKey = UA_ChannelModule_Basic256Sha256_setLocalSymSigningKey;
- channelModule->setLocalSymEncryptingKey = UA_ChannelM_Basic256Sha256_setLocalSymEncryptingKey;
- channelModule->setLocalSymIv = UA_ChannelM_Basic256Sha256_setLocalSymIv;
- channelModule->setRemoteSymSigningKey = UA_ChannelM_Basic256Sha256_setRemoteSymSigningKey;
- channelModule->setRemoteSymEncryptingKey = UA_ChannelM_Basic256Sha256_setRemoteSymEncryptingKey;
- channelModule->setRemoteSymIv = UA_ChannelM_Basic256Sha256_setRemoteSymIv;
- channelModule->compareCertificate = UA_ChannelM_Basic256Sha256_compareCertificate;
+ endpoint->securityMode = securityMode;
+ UA_String_copy(&securityPolicy->policyUri, &endpoint->securityPolicyUri);
+ endpoint->transportProfileUri =
+ UA_STRING_ALLOC("http://opcfoundation.org/UA-Profile/Transport/uatcp-uasc-uabinary");
- retval = UA_OpenSSL_LoadLocalCertificate(&localCertificate, &policy->localCertificate);
+ /* Add security level value for the corresponding message security mode */
+ endpoint->securityLevel = (UA_Byte) securityMode;
- if (retval != UA_STATUSCODE_GOOD)
+ /* Enable all login mechanisms from the access control plugin */
+ UA_StatusCode retval = UA_Array_copy(conf->accessControl.userTokenPolicies,
+ conf->accessControl.userTokenPoliciesSize,
+ (void **)&endpoint->userIdentityTokens,
+ &UA_TYPES[UA_TYPES_USERTOKENPOLICY]);
+ if(retval != UA_STATUSCODE_GOOD){
+ UA_String_clear(&endpoint->securityPolicyUri);
+ UA_String_clear(&endpoint->transportProfileUri);
return retval;
+ }
+ endpoint->userIdentityTokensSize = conf->accessControl.userTokenPoliciesSize;
- /* AsymmetricModule - signature algorithm */
+ UA_String_copy(&securityPolicy->localCertificate, &endpoint->serverCertificate);
+ UA_ApplicationDescription_copy(&conf->applicationDescription, &endpoint->server);
- UA_SecurityPolicySignatureAlgorithm * asySigAlgorithm =
- &asymmetricModule->cryptoModule.signatureAlgorithm;
- asySigAlgorithm->uri = UA_STRING("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256\0");
- asySigAlgorithm->verify = UA_AsySig_Basic256Sha256_Verify;
- asySigAlgorithm->getRemoteSignatureSize = UA_Asym_Basic256Sha256_getRemoteSignatureSize;
- asySigAlgorithm->getLocalSignatureSize = UA_AsySig_Basic256Sha256_getLocalSignatureSize;
- asySigAlgorithm->sign = UA_AsySig_Basic256Sha256_sign;
- asySigAlgorithm->getLocalKeyLength = NULL;
- asySigAlgorithm->getRemoteKeyLength = NULL;
+ return UA_STATUSCODE_GOOD;
+}
- /* AsymmetricModule encryption algorithm */
+static const size_t usernamePasswordsSize = 2;
+static UA_UsernamePasswordLogin usernamePasswords[2] = {
+ {UA_STRING_STATIC("user1"), UA_STRING_STATIC("password")},
+ {UA_STRING_STATIC("user2"), UA_STRING_STATIC("password1")}};
- UA_SecurityPolicyEncryptionAlgorithm * asymEncryAlg =
- &asymmetricModule->cryptoModule.encryptionAlgorithm;
- asymEncryAlg->uri = UA_STRING("http://www.w3.org/2001/04/xmlenc#rsa-oaep\0");
- asymEncryAlg->decrypt = UA_Asym_Basic256Sha256_Decrypt;
- asymEncryAlg->getRemotePlainTextBlockSize =
- UA_AsymEn_Basic256Sha256_getRemotePlainTextBlockSize;
- asymEncryAlg->getRemoteBlockSize = UA_AsymEn_Basic256Sha256_getRemoteBlockSize;
- asymEncryAlg->getRemoteKeyLength = UA_AsymEn_Basic256Sha256_getRemoteKeyLength;
- asymEncryAlg->encrypt = UA_AsymEn_Basic256Sha256_encrypt;
- asymEncryAlg->getLocalKeyLength = UA_AsymEn_Basic256Sha256_getLocalKeyLength;
- asymEncryAlg->getLocalPlainTextBlockSize = NULL;
- asymEncryAlg->getLocalBlockSize = NULL;
+static UA_StatusCode
+setDefaultConfig(UA_ServerConfig *conf) {
+ if(!conf)
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
- /* asymmetricModule */
+ if(conf->nodestore.context == NULL)
+ UA_Nodestore_HashMap(&conf->nodestore);
- asymmetricModule->compareCertificateThumbprint = UA_compareCertificateThumbprint;
- asymmetricModule->makeCertificateThumbprint = UA_makeCertificateThumbprint;
+ /* --> Start setting the default static config <-- */
+ /* Allow user to set his own logger */
+ if(!conf->logger.log)
+ conf->logger = UA_Log_Stdout_;
- /* SymmetricModule */
+ conf->shutdownDelay = 0.0;
- symmetricModule->secureChannelNonceLength = 32;
- symmetricModule->generateNonce = UA_Sym_Basic256Sha256_generateNonce;
- symmetricModule->generateKey = UA_Sym_Basic256Sha256_generateKey;
+ /* Server Description */
+ UA_BuildInfo_clear(&conf->buildInfo);
+ conf->buildInfo.productUri = UA_STRING_ALLOC(PRODUCT_URI);
+ conf->buildInfo.manufacturerName = UA_STRING_ALLOC(MANUFACTURER_NAME);
+ conf->buildInfo.productName = UA_STRING_ALLOC(PRODUCT_NAME);
+ conf->buildInfo.softwareVersion =
+ UA_STRING_ALLOC(VERSION(UA_OPEN62541_VER_MAJOR, UA_OPEN62541_VER_MINOR,
+ UA_OPEN62541_VER_PATCH, UA_OPEN62541_VER_LABEL));
+#ifdef UA_PACK_DEBIAN
+ conf->buildInfo.buildNumber = UA_STRING_ALLOC("deb");
+#else
+ conf->buildInfo.buildNumber = UA_STRING_ALLOC(__DATE__ " " __TIME__);
+#endif
+ conf->buildInfo.buildDate = UA_DateTime_now();
- /* Symmetric encryption Algorithm */
+ UA_ApplicationDescription_clear(&conf->applicationDescription);
+ conf->applicationDescription.applicationUri = UA_STRING_ALLOC(APPLICATION_URI_SERVER);
+ conf->applicationDescription.productUri = UA_STRING_ALLOC(PRODUCT_URI);
+ conf->applicationDescription.applicationName =
+ UA_LOCALIZEDTEXT_ALLOC("en", APPLICATION_NAME);
+ conf->applicationDescription.applicationType = UA_APPLICATIONTYPE_SERVER;
+ /* conf->applicationDescription.gatewayServerUri = UA_STRING_NULL; */
+ /* conf->applicationDescription.discoveryProfileUri = UA_STRING_NULL; */
+ /* conf->applicationDescription.discoveryUrlsSize = 0; */
+ /* conf->applicationDescription.discoveryUrls = NULL; */
- UA_SecurityPolicyEncryptionAlgorithm * symEncryptionAlgorithm =
- &symmetricModule->cryptoModule.encryptionAlgorithm;
- symEncryptionAlgorithm->uri = UA_STRING("http://www.w3.org/2001/04/xmlenc#aes256-cbc\0");
- symEncryptionAlgorithm->getLocalKeyLength = UA_SymEn_Basic256Sha256_getLocalKeyLength;
- symEncryptionAlgorithm->getLocalBlockSize = UA_SymEn_Basic256Sha256_getLocalBlockSize;
- symEncryptionAlgorithm->getRemoteKeyLength = UA_SymEn_Basic256Sha256_getRemoteKeyLength;
- symEncryptionAlgorithm->getRemoteBlockSize = UA_SymEn_Basic256Sha256_getRemoteBlockSize;
- symEncryptionAlgorithm->decrypt = UA_SymEn_Basic256Sha256_decrypt;
- symEncryptionAlgorithm->encrypt = UA_SymEn_Basic256Sha256_encrypt;
- symEncryptionAlgorithm->getLocalPlainTextBlockSize =
- UA_SymEn_Basic256Sha256_getLocalPlainTextBlockSize;
+#ifdef UA_ENABLE_DISCOVERY_MULTICAST
+ UA_MdnsDiscoveryConfiguration_clear(&conf->mdnsConfig);
+ conf->mdnsInterfaceIP = UA_STRING_NULL;
+# if !defined(UA_HAS_GETIFADDR)
+ conf->mdnsIpAddressList = NULL;
+ conf->mdnsIpAddressListSize = 0;
+# endif
+#endif
- /* Symmetric signature Algorithm */
+ /* Custom DataTypes */
+ /* conf->customDataTypesSize = 0; */
+ /* conf->customDataTypes = NULL; */
- UA_SecurityPolicySignatureAlgorithm * symSignatureAlgorithm =
- &symmetricModule->cryptoModule.signatureAlgorithm;
- symSignatureAlgorithm->uri = UA_STRING("http://www.w3.org/2000/09/xmldsig#hmac-sha2-256\0");
- symSignatureAlgorithm->getLocalKeyLength = UA_SymSig_Basic256Sha256_getLocalKeyLength;
- symSignatureAlgorithm->getRemoteKeyLength = UA_SymSig_Basic256Sha256_getRemoteKeyLength;
- symSignatureAlgorithm->getRemoteSignatureSize =
- UA_SymSig_Basic256Sha256_getRemoteSignatureSize;
- symSignatureAlgorithm->verify = UA_SymSig_Basic256Sha256_verify;
- symSignatureAlgorithm->sign = UA_SymSig_Basic256Sha256_sign;
- symSignatureAlgorithm->getLocalSignatureSize = UA_SymSig_Basic256Sha256_getLocalSignatureSize;
+ /* Networking */
+ /* conf->networkLayersSize = 0; */
+ /* conf->networkLayers = NULL; */
+ /* conf->customHostname = UA_STRING_NULL; */
- retval = UA_Policy_New_Context (policy, localPrivateKey, logger);
- if (retval != UA_STATUSCODE_GOOD) {
- UA_ByteString_clear (&policy->localCertificate);
- return retval;
- }
- policy->clear = UA_Policy_Clear_Context;
+ /* Endpoints */
+ /* conf->endpoints = {0, NULL}; */
- /* Use the same signature algorithm as the asymmetric component for
- certificate signing (see standard) */
-
- policy->certificateSigningAlgorithm = policy->asymmetricModule.cryptoModule.signatureAlgorithm;
+ /* Certificate Verification that accepts every certificate. Can be
+ * overwritten when the policy is specialized. */
+ UA_CertificateVerification_AcceptAll(&conf->certificateVerification);
- return UA_STATUSCODE_GOOD;
-}
+ /* * Global Node Lifecycle * */
+ /* conf->nodeLifecycle.constructor = NULL; */
+ /* conf->nodeLifecycle.destructor = NULL; */
+ /* conf->nodeLifecycle.createOptionalChild = NULL; */
+ /* conf->nodeLifecycle.generateChildNodeId = NULL; */
+ conf->modellingRulesOnInstances = UA_TRUE;
-#endif
+ /* Limits for SecureChannels */
+ conf->maxSecureChannels = 40;
+ conf->maxSecurityTokenLifetime = 10 * 60 * 1000; /* 10 minutes */
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/plugins/securityPolicies/openssl/ua_pki_openssl.c" ***********************************/
+ /* Limits for Sessions */
+ conf->maxSessions = 100;
+ conf->maxSessionTimeout = 60.0 * 60.0 * 1000.0; /* 1h */
-/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
- * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
- *
- * Copyright 2020 (c) Wind River Systems, Inc.
- * Copyright 2020 (c) basysKom GmbH
+#ifdef UA_ENABLE_SUBSCRIPTIONS
+ /* Limits for Subscriptions */
+ conf->publishingIntervalLimits = UA_DURATIONRANGE(100.0, 3600.0 * 1000.0);
+ conf->lifeTimeCountLimits = UA_UINT32RANGE(3, 15000);
+ conf->keepAliveCountLimits = UA_UINT32RANGE(1, 100);
+ conf->maxNotificationsPerPublish = 1000;
+ conf->enableRetransmissionQueue = true;
+ conf->maxRetransmissionQueueSize = 0; /* unlimited */
+# ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
+ conf->maxEventsPerNode = 0; /* unlimited */
+# endif
- */
+ /* Limits for MonitoredItems */
+ conf->samplingIntervalLimits = UA_DURATIONRANGE(50.0, 24.0 * 3600.0 * 1000.0);
+ conf->queueSizeLimits = UA_UINT32RANGE(1, 100);
+#endif
-/*
-modification history
---------------------
-21feb20,lan written
-*/
+#ifdef UA_ENABLE_DISCOVERY
+ conf->discoveryCleanupTimeout = 60 * 60;
+#endif
+#ifdef UA_ENABLE_HISTORIZING
+ /* conf->accessHistoryDataCapability = UA_FALSE; */
+ /* conf->maxReturnDataValues = 0; */
+ /* conf->accessHistoryEventsCapability = UA_FALSE; */
+ /* conf->maxReturnEventValues = 0; */
-#ifdef UA_ENABLE_ENCRYPTION_OPENSSL
-#include <openssl/x509.h>
-#include <openssl/x509_vfy.h>
-#include <openssl/x509v3.h>
-#include <openssl/pem.h>
+ /* conf->insertDataCapability = UA_FALSE; */
+ /* conf->insertEventCapability = UA_FALSE; */
+ /* conf->insertAnnotationsCapability = UA_FALSE; */
-typedef struct {
- /*
- * If the folders are defined, we use them to reload the certificates during
- * runtime
- */
+ /* conf->replaceDataCapability = UA_FALSE; */
+ /* conf->replaceEventCapability = UA_FALSE; */
- UA_String trustListFolder;
- UA_String issuerListFolder;
- UA_String revocationListFolder;
+ /* conf->updateDataCapability = UA_FALSE; */
+ /* conf->updateEventCapability = UA_FALSE; */
- STACK_OF(X509) * skIssue;
- STACK_OF(X509) * skTrusted;
- STACK_OF(X509_CRL) * skCrls; /* Revocation list*/
-} CertContext;
+ /* conf->deleteRawCapability = UA_FALSE; */
+ /* conf->deleteEventCapability = UA_FALSE; */
+ /* conf->deleteAtTimeDataCapability = UA_FALSE; */
+#endif
+
+#if UA_MULTITHREADING >= 100
+ conf->maxAsyncOperationQueueSize = 0;
+ conf->asyncOperationTimeout = 120000; /* Async Operation Timeout in ms (2 minutes) */
+#endif
+
+ /* --> Finish setting the default static config <-- */
-static UA_StatusCode
-UA_CertContext_sk_Init (CertContext * context) {
- context->skTrusted = sk_X509_new_null();
- context->skIssue = sk_X509_new_null();
- context->skCrls = sk_X509_CRL_new_null();
- if (context->skTrusted == NULL || context->skIssue == NULL ||
- context->skCrls == NULL) {
- return UA_STATUSCODE_BADOUTOFMEMORY;
- }
return UA_STATUSCODE_GOOD;
}
-static void
-UA_CertContext_sk_free (CertContext * context) {
- sk_X509_pop_free (context->skTrusted, X509_free);
- sk_X509_pop_free (context->skIssue, X509_free);
- sk_X509_CRL_pop_free (context->skCrls, X509_CRL_free);
+UA_EXPORT UA_StatusCode
+UA_ServerConfig_setBasics(UA_ServerConfig* conf) {
+ UA_StatusCode res = setDefaultConfig(conf);
+ UA_LOG_WARNING(&conf->logger, UA_LOGCATEGORY_USERLAND,
+ "AcceptAll Certificate Verification. "
+ "Any remote certificate will be accepted.");
+ return res;
}
-static UA_StatusCode
-UA_CertContext_Init (CertContext * context) {
- (void) memset (context, 0, sizeof (CertContext));
- UA_ByteString_init (&context->trustListFolder);
- UA_ByteString_init (&context->issuerListFolder);
- UA_ByteString_init (&context->revocationListFolder);
- return UA_CertContext_sk_Init (context);
+static UA_StatusCode
+addDefaultNetworkLayers(UA_ServerConfig *conf, UA_UInt16 portNumber,
+ UA_UInt32 sendBufferSize, UA_UInt32 recvBufferSize) {
+ return UA_ServerConfig_addNetworkLayerTCP(conf, portNumber, sendBufferSize, recvBufferSize);
}
-static void
-UA_CertificateVerification_clear (UA_CertificateVerification * cv) {
- if (cv == NULL) {
- return ;
- }
- CertContext * context = (CertContext *) cv->context;
- if (context == NULL) {
- return;
- }
- UA_ByteString_deleteMembers (&context->trustListFolder);
- UA_ByteString_deleteMembers (&context->issuerListFolder);
- UA_ByteString_deleteMembers (&context->revocationListFolder);
+#ifdef UA_ENABLE_WEBSOCKET_SERVER
+UA_EXPORT UA_StatusCode
+UA_ServerConfig_addNetworkLayerWS(UA_ServerConfig *conf, UA_UInt16 portNumber,
+ UA_UInt32 sendBufferSize, UA_UInt32 recvBufferSize, const UA_ByteString* certificate, const UA_ByteString* privateKey) {
+ /* Add a network layer */
+ UA_ServerNetworkLayer *tmp = (UA_ServerNetworkLayer *)
+ UA_realloc(conf->networkLayers,
+ sizeof(UA_ServerNetworkLayer) * (1 + conf->networkLayersSize));
+ if(!tmp)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ conf->networkLayers = tmp;
- UA_CertContext_sk_free (context);
- UA_free (context);
+ UA_ConnectionConfig config = UA_ConnectionConfig_default;
+ if(sendBufferSize > 0)
+ config.sendBufferSize = sendBufferSize;
+ if(recvBufferSize > 0)
+ config.recvBufferSize = recvBufferSize;
- cv->context = NULL;
+ conf->networkLayers[conf->networkLayersSize] =
+ UA_ServerNetworkLayerWS(config, portNumber, certificate, privateKey);
+ if(!conf->networkLayers[conf->networkLayersSize].handle)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ conf->networkLayersSize++;
- return;
+ return UA_STATUSCODE_GOOD;
}
+#endif
-static UA_StatusCode
-UA_skTrusted_Cert2X509 (const UA_ByteString * certificateTrustList,
- size_t certificateTrustListSize,
- CertContext * ctx) {
- size_t i;
+UA_EXPORT UA_StatusCode
+UA_ServerConfig_addNetworkLayerTCP(UA_ServerConfig *conf, UA_UInt16 portNumber,
+ UA_UInt32 sendBufferSize, UA_UInt32 recvBufferSize) {
+ /* Add a network layer */
+ UA_ServerNetworkLayer *tmp = (UA_ServerNetworkLayer *)
+ UA_realloc(conf->networkLayers,
+ sizeof(UA_ServerNetworkLayer) * (1 + conf->networkLayersSize));
+ if(!tmp)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ conf->networkLayers = tmp;
- for (i = 0; i < certificateTrustListSize; i++) {
- X509 * x509 = UA_OpenSSL_LoadCertificate(&certificateTrustList[i]);
+ UA_ConnectionConfig config = UA_ConnectionConfig_default;
+ if (sendBufferSize > 0)
+ config.sendBufferSize = sendBufferSize;
+ if (recvBufferSize > 0)
+ config.recvBufferSize = recvBufferSize;
- if (x509 == NULL) {
- return UA_STATUSCODE_BADINTERNALERROR;
+ conf->networkLayers[conf->networkLayersSize] =
+ UA_ServerNetworkLayerTCP(config, portNumber, 0);
+ if (!conf->networkLayers[conf->networkLayersSize].handle)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ conf->networkLayersSize++;
+
+ return UA_STATUSCODE_GOOD;
+}
+
+UA_EXPORT UA_StatusCode
+UA_ServerConfig_addSecurityPolicyNone(UA_ServerConfig *config,
+ const UA_ByteString *certificate) {
+ /* Allocate the SecurityPolicies */
+ UA_SecurityPolicy *tmp = (UA_SecurityPolicy *)
+ UA_realloc(config->securityPolicies,
+ sizeof(UA_SecurityPolicy) * (1 + config->securityPoliciesSize));
+ if(!tmp)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ config->securityPolicies = tmp;
+
+ /* Populate the SecurityPolicies */
+ UA_ByteString localCertificate = UA_BYTESTRING_NULL;
+ if(certificate)
+ localCertificate = *certificate;
+ UA_StatusCode retval =
+ UA_SecurityPolicy_None(&config->securityPolicies[config->securityPoliciesSize],
+ localCertificate, &config->logger);
+ if(retval != UA_STATUSCODE_GOOD) {
+ if(config->securityPoliciesSize == 0) {
+ UA_free(config->securityPolicies);
+ config->securityPolicies = NULL;
}
- sk_X509_push (ctx->skTrusted, x509);
+ return retval;
}
- return UA_STATUSCODE_GOOD;
+ config->securityPoliciesSize++;
+ return UA_STATUSCODE_GOOD;
}
-static UA_StatusCode
-UA_skIssuer_Cert2X509 (const UA_ByteString * certificateIssuerList,
- size_t certificateIssuerListSize,
- CertContext * ctx) {
- size_t i;
-
- for (i = 0; i < certificateIssuerListSize; i++) {
- X509 * x509 = UA_OpenSSL_LoadCertificate(&certificateIssuerList[i]);
+UA_EXPORT UA_StatusCode
+UA_ServerConfig_addEndpoint(UA_ServerConfig *config, const UA_String securityPolicyUri,
+ UA_MessageSecurityMode securityMode) {
+ /* Allocate the endpoint */
+ UA_EndpointDescription *tmp = (UA_EndpointDescription *)
+ UA_realloc(config->endpoints,
+ sizeof(UA_EndpointDescription) * (1 + config->endpointsSize));
+ if(!tmp) {
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ }
+ config->endpoints = tmp;
- if (x509 == NULL) {
- return UA_STATUSCODE_BADINTERNALERROR;
+ /* Lookup the security policy */
+ const UA_SecurityPolicy *policy = NULL;
+ for (size_t i = 0; i < config->securityPoliciesSize; ++i) {
+ if (UA_String_equal(&securityPolicyUri, &config->securityPolicies[i].policyUri)) {
+ policy = &config->securityPolicies[i];
+ break;
}
- sk_X509_push (ctx->skIssue, x509);
}
+ if (!policy)
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
- return UA_STATUSCODE_GOOD;
-}
+ /* Populate the endpoint */
+ UA_StatusCode retval =
+ createEndpoint(config, &config->endpoints[config->endpointsSize],
+ policy, securityMode);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+ config->endpointsSize++;
-static UA_StatusCode
-UA_skCrls_Cert2X509 (const UA_ByteString * certificateRevocationList,
- size_t certificateRevocationListSize,
- CertContext * ctx) {
- size_t i;
- const unsigned char * pData;
+ return UA_STATUSCODE_GOOD;
+}
- for (i = 0; i < certificateRevocationListSize; i++) {
- pData = certificateRevocationList[i].data;
- X509_CRL * crl = NULL;
+UA_EXPORT UA_StatusCode
+UA_ServerConfig_addAllEndpoints(UA_ServerConfig *config) {
+ /* Allocate the endpoints */
+ UA_EndpointDescription * tmp = (UA_EndpointDescription *)
+ UA_realloc(config->endpoints,
+ sizeof(UA_EndpointDescription) *
+ (2 * config->securityPoliciesSize + config->endpointsSize));
+ if(!tmp) {
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ }
+ config->endpoints = tmp;
- if (certificateRevocationList[i].length > 1 && pData[0] == 0x30 && pData[1] == 0x82) { // Magic number for DER encoded files
- crl = d2i_X509_CRL (NULL, &pData, (long) certificateRevocationList[i].length);
+ /* Populate the endpoints */
+ for(size_t i = 0; i < config->securityPoliciesSize; ++i) {
+ if(UA_String_equal(&UA_SECURITY_POLICY_NONE_URI, &config->securityPolicies[i].policyUri)) {
+ UA_StatusCode retval =
+ createEndpoint(config, &config->endpoints[config->endpointsSize],
+ &config->securityPolicies[i], UA_MESSAGESECURITYMODE_NONE);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+ config->endpointsSize++;
} else {
- BIO* bio = NULL;
-
-#if OPENSSL_VERSION_NUMBER < 0x1000207fL
- bio = BIO_new_mem_buf((void *) certificateRevocationList[i].data,
- (int) certificateRevocationList[i].length);
-#else
- bio = BIO_new_mem_buf((const void *) certificateRevocationList[i].data,
- (int) certificateRevocationList[i].length);
-#endif
- crl = PEM_read_bio_X509_CRL(bio, NULL, NULL, NULL);
- BIO_free(bio);
- }
+ UA_StatusCode retval =
+ createEndpoint(config, &config->endpoints[config->endpointsSize],
+ &config->securityPolicies[i], UA_MESSAGESECURITYMODE_SIGN);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+ config->endpointsSize++;
- if (crl == NULL) {
- return UA_STATUSCODE_BADINTERNALERROR;
+ retval = createEndpoint(config, &config->endpoints[config->endpointsSize],
+ &config->securityPolicies[i],
+ UA_MESSAGESECURITYMODE_SIGNANDENCRYPT);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+ config->endpointsSize++;
}
- sk_X509_CRL_push (ctx->skCrls, crl);
}
- return UA_STATUSCODE_GOOD;
+ return UA_STATUSCODE_GOOD;
}
-#ifdef __linux__
-#include <dirent.h>
-
-static int UA_Certificate_Filter_der_pem (const struct dirent * entry) {
- char *pszFind;
+UA_EXPORT UA_StatusCode
+UA_ServerConfig_setMinimalCustomBuffer(UA_ServerConfig *config, UA_UInt16 portNumber,
+ const UA_ByteString *certificate,
+ UA_UInt32 sendBufferSize,
+ UA_UInt32 recvBufferSize) {
+ if(!config)
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
- /* ignore hidden files */
- if (entry->d_name[0] == '.') return 0;
+ UA_StatusCode retval = setDefaultConfig(config);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_ServerConfig_clean(config);
+ return retval;
+ }
- /* check file extension */
- pszFind = strrchr(entry->d_name, '.');
- if (pszFind == 0)
- return 0;
- pszFind++;
- if (strcmp (pszFind, "der") == 0 || strcmp (pszFind, "pem") == 0)
- return 1;
+ retval = addDefaultNetworkLayers(config, portNumber, sendBufferSize, recvBufferSize);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_ServerConfig_clean(config);
+ return retval;
+ }
- return 0;
-}
+ /* Allocate the SecurityPolicies */
+ retval = UA_ServerConfig_addSecurityPolicyNone(config, certificate);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_ServerConfig_clean(config);
+ return retval;
+ }
-static int UA_Certificate_Filter_crl (const struct dirent * entry) {
- char *pszFind;
+ /* Initialize the Access Control plugin */
+ retval = UA_AccessControl_default(config, true, NULL,
+ &config->securityPolicies[config->securityPoliciesSize-1].policyUri,
+ usernamePasswordsSize, usernamePasswords);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_ServerConfig_clean(config);
+ return retval;
+ }
- /* ignore hidden files */
- if (entry->d_name[0] == '.') return 0;
+ /* Allocate the endpoint */
+ retval = UA_ServerConfig_addEndpoint(config, UA_SECURITY_POLICY_NONE_URI,
+ UA_MESSAGESECURITYMODE_NONE);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_ServerConfig_clean(config);
+ return retval;
+ }
- /* check file extension */
- pszFind = strrchr(entry->d_name, '.');
- if (pszFind == 0)
- return 0;
- pszFind++;
- if (strcmp (pszFind, "crl") == 0)
- return 1;
+ UA_LOG_WARNING(&config->logger, UA_LOGCATEGORY_USERLAND,
+ "AcceptAll Certificate Verification. "
+ "Any remote certificate will be accepted.");
- return 0;
+ return UA_STATUSCODE_GOOD;
}
-static UA_StatusCode
-UA_BuildFullPath (const char * path,
- const char * fileName,
- size_t fullPathBufferLength,
- char * fullPath) {
- size_t pathLen = strlen (path);
- size_t fileNameLen = strlen (fileName);
- if ((pathLen + fileNameLen + 2) > fullPathBufferLength) {
- return UA_STATUSCODE_BADINVALIDARGUMENT;
+#ifdef UA_ENABLE_ENCRYPTION
+
+UA_EXPORT UA_StatusCode
+UA_ServerConfig_addSecurityPolicyBasic128Rsa15(UA_ServerConfig *config,
+ const UA_ByteString *certificate,
+ const UA_ByteString *privateKey) {
+ /* Allocate the SecurityPolicies */
+ UA_SecurityPolicy *tmp = (UA_SecurityPolicy *)
+ UA_realloc(config->securityPolicies,
+ sizeof(UA_SecurityPolicy) * (1 + config->securityPoliciesSize));
+ if(!tmp)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ config->securityPolicies = tmp;
+
+ /* Populate the SecurityPolicies */
+ UA_ByteString localCertificate = UA_BYTESTRING_NULL;
+ UA_ByteString localPrivateKey = UA_BYTESTRING_NULL;
+ if(certificate)
+ localCertificate = *certificate;
+ if(privateKey)
+ localPrivateKey = *privateKey;
+ UA_StatusCode retval =
+ UA_SecurityPolicy_Basic128Rsa15(&config->securityPolicies[config->securityPoliciesSize],
+ localCertificate, localPrivateKey, &config->logger);
+ if(retval != UA_STATUSCODE_GOOD) {
+ if(config->securityPoliciesSize == 0) {
+ UA_free(config->securityPolicies);
+ config->securityPolicies = NULL;
+ }
+ return retval;
}
- strcpy (fullPath, path);
- strcat (fullPath, "/");
- strcat (fullPath, fileName);
+ config->securityPoliciesSize++;
return UA_STATUSCODE_GOOD;
}
-static UA_StatusCode
-UA_loadCertFromFile (const char * fileName,
- UA_ByteString * cert) {
-
- FILE * fp = fopen(fileName, "rb");
-
- if (fp == NULL)
- return UA_STATUSCODE_BADINTERNALERROR;
-
- fseek(fp, 0, SEEK_END);
- cert->length = (size_t) ftell(fp);
- if (UA_ByteString_allocBuffer (cert, cert->length) != UA_STATUSCODE_GOOD) {
- fclose (fp);
+UA_EXPORT UA_StatusCode
+UA_ServerConfig_addSecurityPolicyBasic256(UA_ServerConfig *config,
+ const UA_ByteString *certificate,
+ const UA_ByteString *privateKey) {
+ /* Allocate the SecurityPolicies */
+ UA_SecurityPolicy *tmp = (UA_SecurityPolicy *)
+ UA_realloc(config->securityPolicies,
+ sizeof(UA_SecurityPolicy) * (1 + config->securityPoliciesSize));
+ if(!tmp)
return UA_STATUSCODE_BADOUTOFMEMORY;
+ config->securityPolicies = tmp;
+
+ /* Populate the SecurityPolicies */
+ UA_ByteString localCertificate = UA_BYTESTRING_NULL;
+ UA_ByteString localPrivateKey = UA_BYTESTRING_NULL;
+ if(certificate)
+ localCertificate = *certificate;
+ if(privateKey)
+ localPrivateKey = *privateKey;
+ UA_StatusCode retval =
+ UA_SecurityPolicy_Basic256(&config->securityPolicies[config->securityPoliciesSize],
+ localCertificate, localPrivateKey, &config->logger);
+ if(retval != UA_STATUSCODE_GOOD) {
+ if(config->securityPoliciesSize == 0) {
+ UA_free(config->securityPolicies);
+ config->securityPolicies = NULL;
+ }
+ return retval;
}
- fseek(fp, 0, SEEK_SET);
- size_t readLen = fread (cert->data, 1, cert->length, fp);
- if (readLen != cert->length) {
- UA_ByteString_deleteMembers (cert);
- cert->length = 0;
- fclose (fp);
- return UA_STATUSCODE_BADINTERNALERROR;
- }
- fclose (fp);
+ config->securityPoliciesSize++;
return UA_STATUSCODE_GOOD;
}
-static UA_StatusCode
-UA_ReloadCertFromFolder (CertContext * ctx) {
- UA_StatusCode ret;
- struct dirent ** dirlist = NULL;
- int i;
- int numCertificates;
- char certFile[PATH_MAX];
- UA_ByteString strCert;
- char folderPath[PATH_MAX];
-
- UA_ByteString_init (&strCert);
-
- if (ctx->trustListFolder.length > 0) {
- UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "Reloading the trust-list");
-
- sk_X509_pop_free (ctx->skTrusted, X509_free);
- ctx->skTrusted = sk_X509_new_null();
- if (ctx->skTrusted == NULL) {
- return UA_STATUSCODE_BADOUTOFMEMORY;
+UA_EXPORT UA_StatusCode
+UA_ServerConfig_addSecurityPolicyBasic256Sha256(UA_ServerConfig *config,
+ const UA_ByteString *certificate,
+ const UA_ByteString *privateKey) {
+ /* Allocate the SecurityPolicies */
+ UA_SecurityPolicy *tmp = (UA_SecurityPolicy *)
+ UA_realloc(config->securityPolicies,
+ sizeof(UA_SecurityPolicy) * (1 + config->securityPoliciesSize));
+ if(!tmp)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ config->securityPolicies = tmp;
+
+ /* Populate the SecurityPolicies */
+ UA_ByteString localCertificate = UA_BYTESTRING_NULL;
+ UA_ByteString localPrivateKey = UA_BYTESTRING_NULL;
+ if(certificate)
+ localCertificate = *certificate;
+ if(privateKey)
+ localPrivateKey = *privateKey;
+ UA_StatusCode retval =
+ UA_SecurityPolicy_Basic256Sha256(&config->securityPolicies[config->securityPoliciesSize],
+ localCertificate, localPrivateKey, &config->logger);
+ if(retval != UA_STATUSCODE_GOOD) {
+ if(config->securityPoliciesSize == 0) {
+ UA_free(config->securityPolicies);
+ config->securityPolicies = NULL;
}
+ return retval;
+ }
- (void) memcpy (folderPath, ctx->trustListFolder.data,
- ctx->trustListFolder.length);
- folderPath[ctx->trustListFolder.length] = 0;
- numCertificates = scandir(folderPath, &dirlist,
- UA_Certificate_Filter_der_pem,
- alphasort);
- for (i = 0; i < numCertificates; i++) {
- if (UA_BuildFullPath (folderPath, dirlist[i]->d_name,
- PATH_MAX, certFile) != UA_STATUSCODE_GOOD) {
- continue;
- }
- ret = UA_loadCertFromFile (certFile, &strCert);
- if (ret != UA_STATUSCODE_GOOD) {
- UA_LOG_INFO (UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
- "Failed to load the certificate file %s", certFile);
- continue; /* continue or return ? */
- }
- if (UA_skTrusted_Cert2X509 (&strCert, 1, ctx) != UA_STATUSCODE_GOOD) {
- UA_LOG_INFO (UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
- "Failed to decode the certificate file %s", certFile);
- UA_ByteString_clear (&strCert);
- continue; /* continue or return ? */
- }
- UA_ByteString_clear (&strCert);
+ config->securityPoliciesSize++;
+ return UA_STATUSCODE_GOOD;
+}
+
+UA_EXPORT UA_StatusCode
+UA_ServerConfig_addSecurityPolicyAes128Sha256RsaOaep(UA_ServerConfig *config,
+ const UA_ByteString *certificate,
+ const UA_ByteString *privateKey) {
+ /* Allocate the SecurityPolicies */
+ UA_SecurityPolicy *tmp = (UA_SecurityPolicy *)
+ UA_realloc(config->securityPolicies,
+ sizeof(UA_SecurityPolicy) * (1 + config->securityPoliciesSize));
+ if(!tmp)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ config->securityPolicies = tmp;
+
+ /* Populate the SecurityPolicies */
+ UA_ByteString localCertificate = UA_BYTESTRING_NULL;
+ UA_ByteString localPrivateKey = UA_BYTESTRING_NULL;
+ if(certificate)
+ localCertificate = *certificate;
+ if(privateKey)
+ localPrivateKey = *privateKey;
+ UA_StatusCode retval =
+ UA_SecurityPolicy_Aes128Sha256RsaOaep(&config->securityPolicies[config->securityPoliciesSize],
+ localCertificate, localPrivateKey, &config->logger);
+ if(retval != UA_STATUSCODE_GOOD) {
+ if(config->securityPoliciesSize == 0) {
+ UA_free(config->securityPolicies);
+ config->securityPolicies = NULL;
}
+ return retval;
}
- if (ctx->issuerListFolder.length > 0) {
- UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "Reloading the issuer-list");
+ config->securityPoliciesSize++;
+ return UA_STATUSCODE_GOOD;
+}
- sk_X509_pop_free (ctx->skIssue, X509_free);
- ctx->skIssue = sk_X509_new_null();
- if (ctx->skIssue == NULL) {
- return UA_STATUSCODE_BADOUTOFMEMORY;
- }
+/* Always returns UA_STATUSCODE_GOOD. Logs a warning if policies could not be added. */
+UA_EXPORT UA_StatusCode
+UA_ServerConfig_addAllSecurityPolicies(UA_ServerConfig *config,
+ const UA_ByteString *certificate,
+ const UA_ByteString *privateKey) {
+ /* Populate the SecurityPolicies */
+ UA_ByteString localCertificate = UA_BYTESTRING_NULL;
+ UA_ByteString localPrivateKey = UA_BYTESTRING_NULL;
+ if(certificate)
+ localCertificate = *certificate;
+ if(privateKey)
+ localPrivateKey = *privateKey;
- memcpy (folderPath, ctx->issuerListFolder.data, ctx->issuerListFolder.length);
- folderPath[ctx->issuerListFolder.length] = 0;
- numCertificates = scandir(folderPath, &dirlist,
- UA_Certificate_Filter_der_pem,
- alphasort);
- for (i = 0; i < numCertificates; i++) {
- if (UA_BuildFullPath (folderPath, dirlist[i]->d_name,
- PATH_MAX, certFile) != UA_STATUSCODE_GOOD) {
- continue;
- }
- ret = UA_loadCertFromFile (certFile, &strCert);
- if (ret != UA_STATUSCODE_GOOD) {
- UA_LOG_INFO (UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
- "Failed to load the certificate file %s", certFile);
- continue; /* continue or return ? */
- }
- if (UA_skIssuer_Cert2X509 (&strCert, 1, ctx) != UA_STATUSCODE_GOOD) {
- UA_LOG_INFO (UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
- "Failed to decode the certificate file %s", certFile);
- UA_ByteString_clear (&strCert);
- continue; /* continue or return ? */
- }
- UA_ByteString_clear (&strCert);
- }
+ UA_StatusCode retval = UA_ServerConfig_addSecurityPolicyNone(config, &localCertificate);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_LOG_WARNING(&config->logger, UA_LOGCATEGORY_USERLAND,
+ "Could not add SecurityPolicy#None with error code %s",
+ UA_StatusCode_name(retval));
}
- if (ctx->revocationListFolder.length > 0) {
- UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "Reloading the revocation-list");
+ retval = UA_ServerConfig_addSecurityPolicyBasic128Rsa15(config, &localCertificate, &localPrivateKey);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_LOG_WARNING(&config->logger, UA_LOGCATEGORY_USERLAND,
+ "Could not add SecurityPolicy#Basic128Rsa15 with error code %s",
+ UA_StatusCode_name(retval));
+ }
- sk_X509_CRL_pop_free (ctx->skCrls, X509_CRL_free);
- ctx->skCrls = sk_X509_CRL_new_null();
- if (ctx->skCrls == NULL) {
- return UA_STATUSCODE_BADOUTOFMEMORY;
- }
+ retval = UA_ServerConfig_addSecurityPolicyBasic256(config, &localCertificate, &localPrivateKey);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_LOG_WARNING(&config->logger, UA_LOGCATEGORY_USERLAND,
+ "Could not add SecurityPolicy#Basic256 with error code %s",
+ UA_StatusCode_name(retval));
+ }
- memcpy (folderPath, ctx->revocationListFolder.data, ctx->revocationListFolder.length);
- folderPath[ctx->revocationListFolder.length] = 0;
- numCertificates = scandir(folderPath, &dirlist,
- UA_Certificate_Filter_crl,
- alphasort);
- for (i = 0; i < numCertificates; i++) {
- if (UA_BuildFullPath (folderPath, dirlist[i]->d_name,
- PATH_MAX, certFile) != UA_STATUSCODE_GOOD) {
- continue;
- }
- ret = UA_loadCertFromFile (certFile, &strCert);
- if (ret != UA_STATUSCODE_GOOD) {
- UA_LOG_INFO (UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
- "Failed to load the revocation file %s", certFile);
- continue; /* continue or return ? */
- }
- if (UA_skCrls_Cert2X509 (&strCert, 1, ctx) != UA_STATUSCODE_GOOD) {
- UA_LOG_INFO (UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
- "Failed to decode the revocation file %s", certFile);
- UA_ByteString_clear (&strCert);
- continue; /* continue or return ? */
- }
- UA_ByteString_clear (&strCert);
- }
+ retval = UA_ServerConfig_addSecurityPolicyBasic256Sha256(config, &localCertificate, &localPrivateKey);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_LOG_WARNING(&config->logger, UA_LOGCATEGORY_USERLAND,
+ "Could not add SecurityPolicy#Basic256Sha256 with error code %s",
+ UA_StatusCode_name(retval));
}
- ret = UA_STATUSCODE_GOOD;
- return ret;
-}
+ retval = UA_ServerConfig_addSecurityPolicyAes128Sha256RsaOaep(config, &localCertificate, &localPrivateKey);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_LOG_WARNING(&config->logger, UA_LOGCATEGORY_USERLAND,
+ "Could not add SecurityPolicy#Aes128Sha256RsaOaep with error code %s",
+ UA_StatusCode_name(retval));
+ }
-#endif /* end of __linux__ */
+ return UA_STATUSCODE_GOOD;
+}
-static UA_StatusCode
-UA_X509_Store_CTX_Error_To_UAError (int opensslErr) {
- UA_StatusCode ret;
-
- switch (opensslErr) {
- case X509_V_ERR_CERT_HAS_EXPIRED:
- case X509_V_ERR_CERT_NOT_YET_VALID:
- case X509_V_ERR_CRL_NOT_YET_VALID:
- case X509_V_ERR_CRL_HAS_EXPIRED:
- case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
- case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
- case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD:
- case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD:
- ret = UA_STATUSCODE_BADCERTIFICATETIMEINVALID;
- break;
- case X509_V_ERR_CERT_REVOKED:
- ret = UA_STATUSCODE_BADCERTIFICATEREVOKED;
- break;
- case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
- case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
- case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
- ret = UA_STATUSCODE_BADCERTIFICATEUNTRUSTED;
- break;
- case X509_V_ERR_CERT_SIGNATURE_FAILURE:
- ret = UA_STATUSCODE_BADSECURITYCHECKSFAILED ;
- break;
- default:
- ret = UA_STATUSCODE_BADCERTIFICATEINVALID;
- break;
- }
- return ret;
+UA_EXPORT UA_StatusCode
+UA_ServerConfig_setDefaultWithSecurityPolicies(UA_ServerConfig *conf,
+ UA_UInt16 portNumber,
+ const UA_ByteString *certificate,
+ const UA_ByteString *privateKey,
+ const UA_ByteString *trustList,
+ size_t trustListSize,
+ const UA_ByteString *issuerList,
+ size_t issuerListSize,
+ const UA_ByteString *revocationList,
+ size_t revocationListSize) {
+ UA_StatusCode retval = setDefaultConfig(conf);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_ServerConfig_clean(conf);
+ return retval;
}
-static UA_StatusCode
-UA_CertificateVerification_Verify (void * verificationContext,
- const UA_ByteString * certificate) {
- X509_STORE_CTX* storeCtx;
- X509_STORE* store;
- CertContext * ctx;
- UA_StatusCode ret;
- int opensslRet;
- X509 * certificateX509 = NULL;
+ retval = UA_CertificateVerification_Trustlist(&conf->certificateVerification,
+ trustList, trustListSize,
+ issuerList, issuerListSize,
+ revocationList, revocationListSize);
+ if (retval != UA_STATUSCODE_GOOD)
+ return retval;
- if (verificationContext == NULL) {
- return UA_STATUSCODE_BADINTERNALERROR;
+ retval = addDefaultNetworkLayers(conf, portNumber, 0, 0);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_ServerConfig_clean(conf);
+ return retval;
}
- ctx = (CertContext *) verificationContext;
-
- store = X509_STORE_new();
- storeCtx = X509_STORE_CTX_new();
-
- if (store == NULL || storeCtx == NULL) {
- ret = UA_STATUSCODE_BADOUTOFMEMORY;
- goto cleanup;
+
+ retval = UA_ServerConfig_addAllSecurityPolicies(conf, certificate, privateKey);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_ServerConfig_clean(conf);
+ return retval;
}
-#ifdef __linux__
- ret = UA_ReloadCertFromFolder (ctx);
- if (ret != UA_STATUSCODE_GOOD) {
- goto cleanup;
+
+ UA_CertificateVerification accessControlVerification;
+ retval = UA_CertificateVerification_Trustlist(&accessControlVerification,
+ trustList, trustListSize,
+ issuerList, issuerListSize,
+ revocationList, revocationListSize);
+ retval |= UA_AccessControl_default(conf, true, &accessControlVerification,
+ &conf->securityPolicies[conf->securityPoliciesSize-1].policyUri,
+ usernamePasswordsSize, usernamePasswords);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_ServerConfig_clean(conf);
+ return retval;
}
-#endif
- certificateX509 = UA_OpenSSL_LoadCertificate(certificate);
- if (certificateX509 == NULL) {
- ret = UA_STATUSCODE_BADCERTIFICATEINVALID;
- goto cleanup;
- }
+ retval = UA_ServerConfig_addAllEndpoints(conf);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_ServerConfig_clean(conf);
+ return retval;
+ }
- X509_STORE_set_flags(store, 0);
- opensslRet = X509_STORE_CTX_init (storeCtx, store, certificateX509,
- ctx->skIssue);
- if (opensslRet != 1) {
- ret = UA_STATUSCODE_BADINTERNALERROR;
- goto cleanup;
+ return UA_STATUSCODE_GOOD;
+}
+
+#endif
+
+/***************************/
+/* Default Client Settings */
+/***************************/
+
+UA_Client * UA_Client_new(void) {
+ UA_ClientConfig config;
+ memset(&config, 0, sizeof(UA_ClientConfig));
+ config.logger.log = UA_Log_Stdout_log;
+ config.logger.context = NULL;
+ config.logger.clear = UA_Log_Stdout_clear;
+ return UA_Client_newWithConfig(&config);
+}
+
+UA_StatusCode
+UA_ClientConfig_setDefault(UA_ClientConfig *config) {
+ config->timeout = 5000;
+ config->secureChannelLifeTime = 10 * 60 * 1000; /* 10 minutes */
+
+ if(!config->logger.log) {
+ config->logger.log = UA_Log_Stdout_log;
+ config->logger.context = NULL;
+ config->logger.clear = UA_Log_Stdout_clear;
}
- (void) X509_STORE_CTX_trusted_stack (storeCtx, ctx->skTrusted);
- /* Set crls to ctx */
- if (sk_X509_CRL_num (ctx->skCrls) > 0) {
- X509_STORE_CTX_set0_crls (storeCtx, ctx->skCrls);
+ if (config->sessionLocaleIdsSize > 0 && config->sessionLocaleIds) {
+ UA_Array_delete(config->sessionLocaleIds, config->sessionLocaleIdsSize, &UA_TYPES[UA_TYPES_LOCALEID]);
}
+ config->sessionLocaleIds = NULL;
+ config->sessionLocaleIds = 0;
+
+ config->localConnectionConfig = UA_ConnectionConfig_default;
-#if OPENSSL_VERSION_NUMBER >= 0x1010000fL
- if (X509_STORE_CTX_get_check_issued (storeCtx) (storeCtx,certificateX509, certificateX509) != 1) {
- X509_STORE_CTX_set_flags (storeCtx, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
+ /* Certificate Verification that accepts every certificate. Can be
+ * overwritten when the policy is specialized. */
+ UA_CertificateVerification_AcceptAll(&config->certificateVerification);
+ UA_LOG_WARNING(&config->logger, UA_LOGCATEGORY_USERLAND,
+ "AcceptAll Certificate Verification. "
+ "Any remote certificate will be accepted.");
+
+ /* With encryption enabled, the applicationUri needs to match the URI from
+ * the certificate */
+ config->clientDescription.applicationUri = UA_STRING_ALLOC(APPLICATION_URI);
+ config->clientDescription.applicationType = UA_APPLICATIONTYPE_CLIENT;
+
+ if(config->securityPoliciesSize > 0) {
+ UA_LOG_ERROR(&config->logger, UA_LOGCATEGORY_NETWORK,
+ "Could not initialize a config that already has SecurityPolicies");
+ return UA_STATUSCODE_BADINTERNALERROR;
}
-#else
- if (storeCtx->check_issued(storeCtx,certificateX509, certificateX509) != 1) {
- X509_STORE_CTX_set_flags (storeCtx, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
+
+ config->securityPolicies = (UA_SecurityPolicy*)UA_malloc(sizeof(UA_SecurityPolicy));
+ if(!config->securityPolicies)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ UA_StatusCode retval = UA_SecurityPolicy_None(config->securityPolicies,
+ UA_BYTESTRING_NULL, &config->logger);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_free(config->securityPolicies);
+ config->securityPolicies = NULL;
+ return retval;
}
-#endif
+ config->securityPoliciesSize = 1;
- opensslRet = X509_verify_cert (storeCtx);
- if (opensslRet == 1) {
- ret = UA_STATUSCODE_GOOD;
+ config->initConnectionFunc = UA_ClientConnectionTCP_init; /* for async client */
+ config->pollConnectionFunc = UA_ClientConnectionTCP_poll; /* for async connection */
+
+ config->customDataTypes = NULL;
+ config->stateCallback = NULL;
+ config->connectivityCheckInterval = 0;
+
+ config->requestedSessionTimeout = 1200000; /* requestedSessionTimeout */
+
+ config->inactivityCallback = NULL;
+ config->clientContext = NULL;
+
+#ifdef UA_ENABLE_SUBSCRIPTIONS
+ config->outStandingPublishRequests = 10;
+ config->subscriptionInactivityCallback = NULL;
+#endif
+
+ return UA_STATUSCODE_GOOD;
+}
+
+#ifdef UA_ENABLE_ENCRYPTION
+UA_StatusCode
+UA_ClientConfig_setDefaultEncryption(UA_ClientConfig *config,
+ UA_ByteString localCertificate, UA_ByteString privateKey,
+ const UA_ByteString *trustList, size_t trustListSize,
+ const UA_ByteString *revocationList, size_t revocationListSize) {
+ UA_StatusCode retval = UA_ClientConfig_setDefault(config);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+
+ retval = UA_CertificateVerification_Trustlist(&config->certificateVerification,
+ trustList, trustListSize,
+ NULL, 0,
+ revocationList, revocationListSize);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+
+ /* Populate SecurityPolicies */
+ UA_SecurityPolicy *sp = (UA_SecurityPolicy*)
+ UA_realloc(config->securityPolicies, sizeof(UA_SecurityPolicy) * 5);
+ if(!sp)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ config->securityPolicies = sp;
+
+ retval = UA_SecurityPolicy_Basic128Rsa15(&config->securityPolicies[config->securityPoliciesSize],
+ localCertificate, privateKey, &config->logger);
+ if(retval == UA_STATUSCODE_GOOD) {
+ ++config->securityPoliciesSize;
+ } else {
+ UA_LOG_WARNING(&config->logger, UA_LOGCATEGORY_USERLAND,
+ "Could not add SecurityPolicy#Basic128Rsa15 with error code %s",
+ UA_StatusCode_name(retval));
}
- else {
- /* Return opc founcation CTT tool expected error */
- opensslRet = X509_STORE_CTX_get_error (storeCtx);
- ret = UA_X509_Store_CTX_Error_To_UAError (opensslRet);
+
+ retval = UA_SecurityPolicy_Basic256(&config->securityPolicies[config->securityPoliciesSize],
+ localCertificate, privateKey, &config->logger);
+ if(retval == UA_STATUSCODE_GOOD) {
+ ++config->securityPoliciesSize;
+ } else {
+ UA_LOG_WARNING(&config->logger, UA_LOGCATEGORY_USERLAND,
+ "Could not add SecurityPolicy#Basic256 with error code %s",
+ UA_StatusCode_name(retval));
}
-cleanup:
- if (store != NULL) {
- X509_STORE_free (store);
+
+ retval = UA_SecurityPolicy_Basic256Sha256(&config->securityPolicies[config->securityPoliciesSize],
+ localCertificate, privateKey, &config->logger);
+ if(retval == UA_STATUSCODE_GOOD) {
+ ++config->securityPoliciesSize;
+ } else {
+ UA_LOG_WARNING(&config->logger, UA_LOGCATEGORY_USERLAND,
+ "Could not add SecurityPolicy#Basic256Sha256 with error code %s",
+ UA_StatusCode_name(retval));
}
- if (storeCtx != NULL) {
- X509_STORE_CTX_free (storeCtx);
+
+ retval = UA_SecurityPolicy_Aes128Sha256RsaOaep(&config->securityPolicies[config->securityPoliciesSize],
+ localCertificate, privateKey, &config->logger);
+ if(retval == UA_STATUSCODE_GOOD) {
+ ++config->securityPoliciesSize;
+ } else {
+ UA_LOG_WARNING(&config->logger, UA_LOGCATEGORY_USERLAND,
+ "Could not add SecurityPolicy#Aes128Sha256RsaOaep with error code %s",
+ UA_StatusCode_name(retval));
}
- if (certificateX509 != NULL) {
- X509_free (certificateX509);
+
+ if(config->securityPoliciesSize == 0) {
+ UA_free(config->securityPolicies);
+ config->securityPolicies = NULL;
}
- return ret;
+
+ return UA_STATUSCODE_GOOD;
}
+#endif
+
+/**** amalgamated original file "/plugins/crypto/ua_pki_none.c" ****/
+
+/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
+ * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
+ *
+ * Copyright 2020 (c) Julius Pfrommer, Fraunhofer IOSB
+ */
+
static UA_StatusCode
-UA_VerifyCertificateAllowAll (void * verificationContext,
- const UA_ByteString * certificate) {
- (void) verificationContext;
- (void) certificate;
- return UA_STATUSCODE_GOOD;
+verifyCertificateAllowAll(void *verificationContext,
+ const UA_ByteString *certificate) {
+ return UA_STATUSCODE_GOOD;
}
-static UA_StatusCode
-UA_CertificateVerification_VerifyApplicationURI (void * verificationContext,
- const UA_ByteString * certificate,
- const UA_String * applicationURI) {
- (void) verificationContext;
+static UA_StatusCode
+verifyApplicationURIAllowAll(void *verificationContext,
+ const UA_ByteString *certificate,
+ const UA_String *applicationURI) {
+ return UA_STATUSCODE_GOOD;
+}
- const unsigned char * pData;
- X509 * certificateX509;
- UA_String subjectURI;
- GENERAL_NAMES * pNames;
- int i;
- UA_StatusCode ret;
-
- pData = certificate->data;
- if (pData == NULL) {
- return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
- }
+static void
+clearVerifyAllowAll(UA_CertificateVerification *cv) {
- certificateX509 = UA_OpenSSL_LoadCertificate(certificate);
- if (certificateX509 == NULL) {
- return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
- }
+}
- pNames = (GENERAL_NAMES *) X509_get_ext_d2i(certificateX509, NID_subject_alt_name,
- NULL, NULL);
- if (pNames == NULL) {
- X509_free (certificateX509);
- return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
- }
- for (i = 0; i < sk_GENERAL_NAME_num (pNames); i++) {
- GENERAL_NAME * value = sk_GENERAL_NAME_value (pNames, i);
- if (value->type == GEN_URI) {
- subjectURI.length = (size_t) (value->d.ia5->length);
- subjectURI.data = (UA_Byte *) UA_malloc (subjectURI.length);
- if (subjectURI.data == NULL) {
- X509_free (certificateX509);
- sk_GENERAL_NAME_pop_free(pNames, GENERAL_NAME_free);
- return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
- }
- (void) memcpy (subjectURI.data, value->d.ia5->data, subjectURI.length);
- break;
- }
-
- }
+void UA_CertificateVerification_AcceptAll(UA_CertificateVerification *cv) {
+ cv->verifyCertificate = verifyCertificateAllowAll;
+ cv->verifyApplicationURI = verifyApplicationURIAllowAll;
+ cv->clear = clearVerifyAllowAll;
+}
- ret = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
- if (UA_Bstrstr (subjectURI.data, subjectURI.length,
- applicationURI->data, applicationURI->length) != NULL) {
- ret = UA_STATUSCODE_GOOD;
- }
+/**** amalgamated original file "/plugins/crypto/ua_securitypolicy_none.c" ****/
- X509_free (certificateX509);
- sk_GENERAL_NAME_pop_free(pNames, GENERAL_NAME_free);
- UA_String_clear (&subjectURI);
- return ret;
+/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
+ * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
+ *
+ * Copyright 2017-2018 (c) Mark Giraud, Fraunhofer IOSB
+ * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
+ */
+
+
+#ifdef UA_ENABLE_ENCRYPTION_MBEDTLS
+#endif
+
+#if defined(UA_ENABLE_ENCRYPTION_OPENSSL) || defined(UA_ENABLE_ENCRYPTION_LIBRESSL)
+#endif
+
+static UA_StatusCode
+verify_none(void *channelContext,
+ const UA_ByteString *message,
+ const UA_ByteString *signature) {
+ return UA_STATUSCODE_GOOD;
}
-/* main entry */
+static UA_StatusCode
+sign_none(void *channelContext, const UA_ByteString *message,
+ UA_ByteString *signature) {
+ return UA_STATUSCODE_GOOD;
+}
-UA_StatusCode
-UA_CertificateVerification_Trustlist(UA_CertificateVerification * cv,
- const UA_ByteString * certificateTrustList,
- size_t certificateTrustListSize,
- const UA_ByteString * certificateIssuerList,
- size_t certificateIssuerListSize,
- const UA_ByteString * certificateRevocationList,
- size_t certificateRevocationListSize) {
- UA_StatusCode ret;
+static size_t
+length_none(const void *channelContext) {
+ return 0;
+}
- if (cv == NULL) {
+static UA_StatusCode
+encrypt_none(void *channelContext, UA_ByteString *data) {
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_StatusCode
+decrypt_none(void *channelContext, UA_ByteString *data) {
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_StatusCode
+makeThumbprint_none(const UA_SecurityPolicy *securityPolicy,
+ const UA_ByteString *certificate,
+ UA_ByteString *thumbprint) {
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_StatusCode
+compareThumbprint_none(const UA_SecurityPolicy *securityPolicy,
+ const UA_ByteString *certificateThumbprint) {
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_StatusCode
+generateKey_none(void *policyContext, const UA_ByteString *secret,
+ const UA_ByteString *seed, UA_ByteString *out) {
+ return UA_STATUSCODE_GOOD;
+}
+
+/* Use the non-cryptographic RNG to set the nonce */
+static UA_StatusCode
+generateNonce_none(void *policyContext, UA_ByteString *out) {
+ if(out == NULL)
return UA_STATUSCODE_BADINTERNALERROR;
- }
- CertContext * context = (CertContext *) UA_malloc (sizeof (CertContext));
- if (context == NULL) {
- return UA_STATUSCODE_BADOUTOFMEMORY;
- }
- ret = UA_CertContext_Init (context);
- if (ret != UA_STATUSCODE_GOOD) {
- return ret;
- }
+ if(out->length == 0)
+ return UA_STATUSCODE_GOOD;
- cv->verifyApplicationURI = UA_CertificateVerification_VerifyApplicationURI;
- cv->clear = UA_CertificateVerification_clear;
- cv->context = context;
- if (certificateTrustListSize > 0)
- cv->verifyCertificate = UA_CertificateVerification_Verify;
- else
- cv->verifyCertificate = UA_VerifyCertificateAllowAll;
-
- if (certificateTrustListSize > 0) {
- if (UA_skTrusted_Cert2X509 (certificateTrustList, certificateTrustListSize,
- context) != UA_STATUSCODE_GOOD) {
- ret = UA_STATUSCODE_BADINTERNALERROR;
- goto errout;
- }
+ /* Fill blocks of four byte */
+ size_t i = 0;
+ while(i + 3 < out->length) {
+ UA_UInt32 randNumber = UA_UInt32_random();
+ memcpy(&out->data[i], &randNumber, 4);
+ i = i+4;
}
- if (certificateIssuerListSize > 0) {
- if (UA_skIssuer_Cert2X509 (certificateIssuerList, certificateIssuerListSize,
- context) != UA_STATUSCODE_GOOD) {
- ret = UA_STATUSCODE_BADINTERNALERROR;
- goto errout;
- }
- }
+ /* Fill the remaining byte */
+ UA_UInt32 randNumber = UA_UInt32_random();
+ memcpy(&out->data[i], &randNumber, out->length % 4);
- if (certificateRevocationListSize > 0) {
- if (UA_skCrls_Cert2X509 (certificateRevocationList, certificateRevocationListSize,
- context) != UA_STATUSCODE_GOOD) {
- ret = UA_STATUSCODE_BADINTERNALERROR;
- goto errout;
- }
- }
+ return UA_STATUSCODE_GOOD;
+}
+static UA_StatusCode
+newContext_none(const UA_SecurityPolicy *securityPolicy,
+ const UA_ByteString *remoteCertificate,
+ void **channelContext) {
return UA_STATUSCODE_GOOD;
+}
-errout:
- UA_CertificateVerification_clear (cv);
- return ret;
+static void
+deleteContext_none(void *channelContext) {
+}
+
+static UA_StatusCode
+setContextValue_none(void *channelContext,
+ const UA_ByteString *key) {
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_StatusCode
+compareCertificate_none(const void *channelContext,
+ const UA_ByteString *certificate) {
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_StatusCode
+updateCertificateAndPrivateKey_none(UA_SecurityPolicy *policy,
+ const UA_ByteString newCertificate,
+ const UA_ByteString newPrivateKey) {
+ UA_ByteString_clear(&policy->localCertificate);
+ UA_ByteString_copy(&newCertificate, &policy->localCertificate);
+ return UA_STATUSCODE_GOOD;
+}
+
+
+static void
+policy_clear_none(UA_SecurityPolicy *policy) {
+ UA_ByteString_clear(&policy->localCertificate);
}
-#ifdef __linux__ /* Linux only so far */
UA_StatusCode
-UA_CertificateVerification_CertFolders(UA_CertificateVerification * cv,
- const char * trustListFolder,
- const char * issuerListFolder,
- const char * revocationListFolder) {
- UA_StatusCode ret;
- if (cv == NULL) {
- return UA_STATUSCODE_BADINTERNALERROR;
- }
+UA_SecurityPolicy_None(UA_SecurityPolicy *policy, const UA_ByteString localCertificate,
+ const UA_Logger *logger) {
+ policy->policyContext = (void *)(uintptr_t)logger;
+ policy->policyUri = UA_STRING("http://opcfoundation.org/UA/SecurityPolicy#None");
+ policy->logger = logger;
- CertContext * context = (CertContext *) UA_malloc (sizeof (CertContext));
- if (context == NULL) {
- return UA_STATUSCODE_BADOUTOFMEMORY;
- }
- ret = UA_CertContext_Init (context);
- if (ret != UA_STATUSCODE_GOOD) {
- return ret;
- }
+#ifdef UA_ENABLE_ENCRYPTION_MBEDTLS
+ UA_mbedTLS_LoadLocalCertificate(&localCertificate, &policy->localCertificate);
+#elif defined(UA_ENABLE_ENCRYPTION_OPENSSL) || defined(UA_ENABLE_ENCRYPTION_LIBRESSL)
+ UA_OpenSSL_LoadLocalCertificate(&localCertificate, &policy->localCertificate);
+#else
+ UA_ByteString_copy(&localCertificate, &policy->localCertificate);
+#endif
- cv->verifyApplicationURI = UA_CertificateVerification_VerifyApplicationURI;
- cv->clear = UA_CertificateVerification_clear;
- cv->context = context;
- cv->verifyCertificate = UA_CertificateVerification_Verify;
+ policy->symmetricModule.generateKey = generateKey_none;
+ policy->symmetricModule.generateNonce = generateNonce_none;
- /* Only set the folder paths. They will be reloaded during runtime. */
+ UA_SecurityPolicySignatureAlgorithm *sym_signatureAlgorithm =
+ &policy->symmetricModule.cryptoModule.signatureAlgorithm;
+ sym_signatureAlgorithm->uri = UA_STRING_NULL;
+ sym_signatureAlgorithm->verify = verify_none;
+ sym_signatureAlgorithm->sign = sign_none;
+ sym_signatureAlgorithm->getLocalSignatureSize = length_none;
+ sym_signatureAlgorithm->getRemoteSignatureSize = length_none;
+ sym_signatureAlgorithm->getLocalKeyLength = length_none;
+ sym_signatureAlgorithm->getRemoteKeyLength = length_none;
- context->trustListFolder = UA_STRING_ALLOC(trustListFolder);
- context->issuerListFolder = UA_STRING_ALLOC(issuerListFolder);
- context->revocationListFolder = UA_STRING_ALLOC(revocationListFolder);
+ UA_SecurityPolicyEncryptionAlgorithm *sym_encryptionAlgorithm =
+ &policy->symmetricModule.cryptoModule.encryptionAlgorithm;
+ sym_encryptionAlgorithm->uri = UA_STRING_NULL;
+ sym_encryptionAlgorithm->encrypt = encrypt_none;
+ sym_encryptionAlgorithm->decrypt = decrypt_none;
+ sym_encryptionAlgorithm->getLocalKeyLength = length_none;
+ sym_encryptionAlgorithm->getRemoteKeyLength = length_none;
+ sym_encryptionAlgorithm->getRemoteBlockSize = length_none;
+ sym_encryptionAlgorithm->getRemotePlainTextBlockSize = length_none;
+ policy->symmetricModule.secureChannelNonceLength = 0;
+
+ policy->asymmetricModule.makeCertificateThumbprint = makeThumbprint_none;
+ policy->asymmetricModule.compareCertificateThumbprint = compareThumbprint_none;
+
+ // This only works for none since symmetric and asymmetric crypto modules do the same i.e. nothing
+ policy->asymmetricModule.cryptoModule = policy->symmetricModule.cryptoModule;
+
+ // Use the same signing algorithm as for asymmetric signing
+ policy->certificateSigningAlgorithm = policy->asymmetricModule.cryptoModule.signatureAlgorithm;
+
+ policy->channelModule.newContext = newContext_none;
+ policy->channelModule.deleteContext = deleteContext_none;
+ policy->channelModule.setLocalSymEncryptingKey = setContextValue_none;
+ policy->channelModule.setLocalSymSigningKey = setContextValue_none;
+ policy->channelModule.setLocalSymIv = setContextValue_none;
+ policy->channelModule.setRemoteSymEncryptingKey = setContextValue_none;
+ policy->channelModule.setRemoteSymSigningKey = setContextValue_none;
+ policy->channelModule.setRemoteSymIv = setContextValue_none;
+ policy->channelModule.compareCertificate = compareCertificate_none;
+ policy->updateCertificateAndPrivateKey = updateCertificateAndPrivateKey_none;
+ policy->clear = policy_clear_none;
return UA_STATUSCODE_GOOD;
}
+
+/**** amalgamated original file "/plugins/ua_log_syslog.c" ****/
+
+/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
+ * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
+ *
+ * Copyright 2020 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
+ */
+
+
+#if defined(__linux__) || defined(__unix__)
+
+#include <syslog.h>
+
+const char *syslogLevelNames[6] = {"trace", "debug", "info",
+ "warn", "error", "fatal"};
+const char *syslogCategoryNames[7] = {"network", "channel", "session", "server",
+ "client", "userland", "securitypolicy"};
+
+#ifdef __clang__
+__attribute__((__format__(__printf__, 4 , 0)))
#endif
+static void
+UA_Log_Syslog_log(void *context, UA_LogLevel level, UA_LogCategory category,
+ const char *msg, va_list args) {
+ /* Assume that context is casted to UA_LogLevel */
+ if(context != NULL && (UA_LogLevel)(uintptr_t)context > level)
+ return;
-#endif /* end of UA_ENABLE_ENCRYPTION_OPENSSL */
+ int priority = LOG_INFO;
+ switch(level) {
+ case UA_LOGLEVEL_DEBUG:
+ priority = LOG_DEBUG;
+ break;
+ case UA_LOGLEVEL_INFO:
+ priority = LOG_INFO;
+ break;
+ case UA_LOGLEVEL_WARNING:
+ priority = LOG_WARNING;
+ break;
+ case UA_LOGLEVEL_ERROR:
+ priority = LOG_ERR;
+ break;
+ case UA_LOGLEVEL_FATAL:
+ priority = LOG_CRIT;
+ break;
+ case UA_LOGLEVEL_TRACE:
+ default:
+ return;
+ }
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/plugins/historydata/ua_history_data_backend_memory.c" ***********************************/
+#define LOGBUFSIZE 512
+ char logbuf[LOGBUFSIZE];
+ int pos = snprintf(logbuf, LOGBUFSIZE, "[%s/%s] ",
+ syslogLevelNames[level], syslogCategoryNames[category]);
+ if(pos < 0) {
+ syslog(LOG_WARNING, "Log message too long for syslog");
+ return;
+ }
+ pos = vsnprintf(&logbuf[pos], LOGBUFSIZE - (size_t)pos, msg, args);
+ if(pos < 0) {
+ syslog(LOG_WARNING, "Log message too long for syslog");
+ return;
+ }
+
+ syslog(priority, "%s", logbuf);
+}
+
+static void
+UA_Log_Syslog_clear(void *logContext) {
+ /* closelog is optional. We don't use it as several loggers might be
+ * instantiated in parallel. */
+ /* closelog(); */
+}
+
+UA_Logger
+UA_Log_Syslog(void) {
+ return UA_Log_Syslog_withLevel(UA_LOGLEVEL_TRACE);
+}
+
+UA_Logger
+UA_Log_Syslog_withLevel(UA_LogLevel minlevel) {
+ UA_Logger logger = {UA_Log_Syslog_log, (void*)minlevel, UA_Log_Syslog_clear};
+ return logger;
+}
+
+#endif
+
+/**** amalgamated original file "/plugins/historydata/ua_history_data_backend_memory.c" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -65084,9 +73727,9 @@ typedef struct {
} UA_DataValueMemoryStoreItem;
static void
-UA_DataValueMemoryStoreItem_deleteMembers(UA_DataValueMemoryStoreItem* item) {
- UA_DateTime_deleteMembers(&item->timestamp);
- UA_DataValue_deleteMembers(&item->value);
+UA_DataValueMemoryStoreItem_clear(UA_DataValueMemoryStoreItem* item) {
+ UA_DateTime_clear(&item->timestamp);
+ UA_DataValue_clear(&item->value);
}
typedef struct {
@@ -65097,10 +73740,10 @@ typedef struct {
} UA_NodeIdStoreContextItem_backend_memory;
static void
-UA_NodeIdStoreContextItem_deleteMembers(UA_NodeIdStoreContextItem_backend_memory* item) {
- UA_NodeId_deleteMembers(&item->nodeId);
+UA_NodeIdStoreContextItem_clear(UA_NodeIdStoreContextItem_backend_memory* item) {
+ UA_NodeId_clear(&item->nodeId);
for (size_t i = 0; i < item->storeEnd; ++i) {
- UA_DataValueMemoryStoreItem_deleteMembers(item->dataStore[i]);
+ UA_DataValueMemoryStoreItem_clear(item->dataStore[i]);
UA_free(item->dataStore[i]);
}
UA_free(item->dataStore);
@@ -65114,9 +73757,9 @@ typedef struct {
} UA_MemoryStoreContext;
static void
-UA_MemoryStoreContext_deleteMembers(UA_MemoryStoreContext* ctx) {
+UA_MemoryStoreContext_clear(UA_MemoryStoreContext* ctx) {
for (size_t i = 0; i < ctx->storeEnd; ++i) {
- UA_NodeIdStoreContextItem_deleteMembers(&ctx->dataStore[i]);
+ UA_NodeIdStoreContextItem_clear(&ctx->dataStore[i]);
}
UA_free(ctx->dataStore);
memset(ctx, 0, sizeof(UA_MemoryStoreContext));
@@ -65142,7 +73785,7 @@ getNewNodeIdContext_backend_memory(UA_MemoryStoreContext* context,
UA_NodeId_copy(nodeId, &item->nodeId);
UA_DataValueMemoryStoreItem ** store = (UA_DataValueMemoryStoreItem **)UA_calloc(ctx->initialStoreSize, sizeof(UA_DataValueMemoryStoreItem*));
if (!store) {
- UA_NodeIdStoreContextItem_deleteMembers(item);
+ UA_NodeIdStoreContextItem_clear(item);
return NULL;
}
item->dataStore = store;
@@ -65299,7 +73942,7 @@ serverSetHistoryData_backend_memory(UA_Server *server,
static void
UA_MemoryStoreContext_delete(UA_MemoryStoreContext* ctx) {
- UA_MemoryStoreContext_deleteMembers(ctx);
+ UA_MemoryStoreContext_clear(ctx);
UA_free(ctx);
}
@@ -65309,7 +73952,7 @@ getEnd_backend_memory(UA_Server *server,
const UA_NodeId *sessionId,
void *sessionContext,
const UA_NodeId * nodeId) {
- const UA_NodeIdStoreContextItem_backend_memory* item = getNodeIdStoreContextItem_backend_memory((UA_MemoryStoreContext*)context, server, nodeId);;
+ const UA_NodeIdStoreContextItem_backend_memory* item = getNodeIdStoreContextItem_backend_memory((UA_MemoryStoreContext*)context, server, nodeId);
return item->storeEnd;
}
@@ -65319,7 +73962,7 @@ lastIndex_backend_memory(UA_Server *server,
const UA_NodeId *sessionId,
void *sessionContext,
const UA_NodeId * nodeId) {
- const UA_NodeIdStoreContextItem_backend_memory* item = getNodeIdStoreContextItem_backend_memory((UA_MemoryStoreContext*)context, server, nodeId);;
+ const UA_NodeIdStoreContextItem_backend_memory* item = getNodeIdStoreContextItem_backend_memory((UA_MemoryStoreContext*)context, server, nodeId);
if (item->storeEnd == 0)
return 0;
return item->storeEnd - 1;
@@ -65350,7 +73993,7 @@ timestampsToReturnSupported_backend_memory(UA_Server *server,
void *sessionContext,
const UA_NodeId *nodeId,
const UA_TimestampsToReturn timestampsToReturn) {
- const UA_NodeIdStoreContextItem_backend_memory* item = getNodeIdStoreContextItem_backend_memory((UA_MemoryStoreContext*)context, server, nodeId);;
+ const UA_NodeIdStoreContextItem_backend_memory* item = getNodeIdStoreContextItem_backend_memory((UA_MemoryStoreContext*)context, server, nodeId);
if (item->storeEnd == 0) {
return true;
}
@@ -65374,7 +74017,7 @@ getDataValue_backend_memory(UA_Server *server,
const UA_NodeId *sessionId,
void *sessionContext,
const UA_NodeId * nodeId, size_t index) {
- const UA_NodeIdStoreContextItem_backend_memory* item = getNodeIdStoreContextItem_backend_memory((UA_MemoryStoreContext*)context, server, nodeId);;
+ const UA_NodeIdStoreContextItem_backend_memory* item = getNodeIdStoreContextItem_backend_memory((UA_MemoryStoreContext*)context, server, nodeId);
return &item->dataStore[index]->value;
}
@@ -65413,7 +74056,7 @@ copyDataValues_backend_memory(UA_Server *server,
return UA_STATUSCODE_BADCONTINUATIONPOINTINVALID;
}
}
- const UA_NodeIdStoreContextItem_backend_memory* item = getNodeIdStoreContextItem_backend_memory((UA_MemoryStoreContext*)context, server, nodeId);;
+ const UA_NodeIdStoreContextItem_backend_memory* item = getNodeIdStoreContextItem_backend_memory((UA_MemoryStoreContext*)context, server, nodeId);
size_t index = startIndex;
size_t counter = 0;
size_t skipedValues = 0;
@@ -65521,7 +74164,7 @@ replaceDataValue_backend_memory(UA_Server *server,
MATCH_EQUAL);
if (index == item->storeEnd)
return UA_STATUSCODE_BADNOENTRYEXISTS;
- UA_DataValue_deleteMembers(&item->dataStore[index]->value);
+ UA_DataValue_clear(&item->dataStore[index]->value);
UA_DataValue_copy(value, &item->dataStore[index]->value);
return UA_STATUSCODE_GOOD;
}
@@ -65606,7 +74249,7 @@ removeDataValue_backend_memory(UA_Server *server,
}
#ifndef __clang_analyzer__
for (size_t i = index1; i < index2; ++i) {
- UA_DataValueMemoryStoreItem_deleteMembers(item->dataStore[i]);
+ UA_DataValueMemoryStoreItem_clear(item->dataStore[i]);
UA_free(item->dataStore[i]);
}
memmove(&item->dataStore[index1], &item->dataStore[index2], sizeof(UA_DataValueMemoryStoreItem*) * (item->storeEnd - index2));
@@ -65623,7 +74266,8 @@ deleteMembers_backend_memory(UA_HistoryDataBackend *backend)
{
if (backend == NULL || backend->context == NULL)
return;
- UA_MemoryStoreContext_deleteMembers((UA_MemoryStoreContext*)backend->context);
+ UA_MemoryStoreContext_clear((UA_MemoryStoreContext*)backend->context);
+ UA_free(backend->context);
}
@@ -65664,14 +74308,14 @@ UA_HistoryDataBackend_Memory(size_t initialNodeIdStoreSize, size_t initialDataSt
}
void
-UA_HistoryDataBackend_Memory_deleteMembers(UA_HistoryDataBackend *backend)
+UA_HistoryDataBackend_Memory_clear(UA_HistoryDataBackend *backend)
{
UA_MemoryStoreContext *ctx = (UA_MemoryStoreContext*)backend->context;
UA_MemoryStoreContext_delete(ctx);
memset(backend, 0, sizeof(UA_HistoryDataBackend));
}
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/plugins/historydata/ua_history_data_gathering_default.c" ***********************************/
+/**** amalgamated original file "/plugins/historydata/ua_history_data_gathering_default.c" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -65801,6 +74445,7 @@ registerNodeId_gathering_default(UA_Server *server,
ctx->storeSize = 0;
return UA_STATUSCODE_BADOUTOFMEMORY;
}
+ memset(&ctx->dataStore[ctx->storeSize], 0, (newStoreSize - ctx->storeSize) * sizeof(UA_NodeIdStoreContextItem_gathering_default));
ctx->storeSize = newStoreSize;
}
UA_NodeId_copy(nodeId, &ctx->dataStore[ctx->storeEnd].nodeId);
@@ -65830,7 +74475,7 @@ deleteMembers_gathering_default(UA_HistoryDataGathering *gathering)
return;
UA_NodeIdStoreContext *ctx = (UA_NodeIdStoreContext*)gathering->context;
for (size_t i = 0; i < ctx->storeEnd; ++i) {
- UA_NodeId_deleteMembers(&ctx->dataStore[i].nodeId);
+ UA_NodeId_clear(&ctx->dataStore[i].nodeId);
// There is still a monitored item present for this gathering
// You need to remove it with UA_Server_deleteMonitoredItem
UA_assert(ctx->dataStore[i].monitoredResult.monitoredItemId == 0);
@@ -65900,7 +74545,7 @@ UA_HistoryDataGathering_Default(size_t initialNodeIdStoreSize)
return gathering;
}
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/plugins/historydata/ua_history_database_default.c" ***********************************/
+/**** amalgamated original file "/plugins/historydata/ua_history_database_default.c" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -66192,7 +74837,7 @@ getHistoryData_service_default(const UA_HistoryDataBackend* backend,
if(backendOutContinuationPoint.length > 0)
memcpy(outContinuationPoint->data + sizeof(size_t), backendOutContinuationPoint.data, backendOutContinuationPoint.length);
}
- UA_ByteString_deleteMembers(&backendOutContinuationPoint);
+ UA_ByteString_clear(&backendOutContinuationPoint);
return UA_STATUSCODE_GOOD;
}
@@ -66233,15 +74878,14 @@ updateData_service_default(UA_Server *server,
return;
}
+ UA_ServerConfig *config = UA_Server_getConfig(server);
result->operationResultsSize = details->updateValuesSize;
result->operationResults = (UA_StatusCode*)UA_Array_new(result->operationResultsSize, &UA_TYPES[UA_TYPES_STATUSCODE]);
for (size_t i = 0; i < details->updateValuesSize; ++i) {
- if (!UA_Server_AccessControl_allowHistoryUpdateUpdateData(server,
- sessionId,
- sessionContext,
- &details->nodeId,
- details->performInsertReplace,
- &details->updateValues[i])) {
+ if (config->accessControl.allowHistoryUpdateUpdateData &&
+ !config->accessControl.allowHistoryUpdateUpdateData(server, &config->accessControl, sessionId, sessionContext,
+ &details->nodeId, details->performInsertReplace,
+ &details->updateValues[i])) {
result->operationResults[i] = UA_STATUSCODE_BADUSERACCESSDENIED;
continue;
}
@@ -66338,13 +74982,11 @@ deleteRawModified_service_default(UA_Server *server,
return;
}
- if (!UA_Server_AccessControl_allowHistoryUpdateDeleteRawModified(server,
- sessionId,
- sessionContext,
- &details->nodeId,
- details->startTime,
- details->endTime,
- details->isDeleteModified)) {
+ UA_ServerConfig *config = UA_Server_getConfig(server);
+ if (config->accessControl.allowHistoryUpdateDeleteRawModified &&
+ !config->accessControl.allowHistoryUpdateDeleteRawModified(server,
+ &config->accessControl, sessionId, sessionContext, &details->nodeId,
+ details->startTime, details->endTime, details->isDeleteModified)) {
result->statusCode = UA_STATUSCODE_BADUSERACCESSDENIED;
return;
}
@@ -66531,7 +75173,7 @@ UA_HistoryDatabase_default(UA_HistoryDataGathering gathering)
return hdb;
}
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/arch/posix/ua_clock.c" ***********************************/
+/**** amalgamated original file "/arch/posix/ua_clock.c" ****/
/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
* See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
@@ -66545,7 +75187,6 @@ UA_HistoryDatabase_default(UA_HistoryDataGathering gathering)
#include <time.h>
-
#include <sys/time.h>
#if defined(__APPLE__) || defined(__MACH__)
@@ -66593,7 +75234,7 @@ UA_DateTime UA_DateTime_nowMonotonic(void) {
#endif /* UA_ARCHITECTURE_POSIX */
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/arch/posix/ua_architecture_functions.c" ***********************************/
+/**** amalgamated original file "/arch/posix/ua_architecture_functions.c" ****/
/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
* See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
@@ -66606,10 +75247,10 @@ UA_DateTime UA_DateTime_nowMonotonic(void) {
/* Global malloc singletons */
#ifdef UA_ENABLE_MALLOC_SINGLETON
-void * (*UA_globalMalloc)(size_t size) = malloc;
-void (*UA_globalFree)(void *ptr) = free;
-void * (*UA_globalCalloc)(size_t nelem, size_t elsize) = calloc;
-void * (*UA_globalRealloc)(void *ptr, size_t size) = realloc;
+UA_EXPORT UA_THREAD_LOCAL void * (*UA_mallocSingleton)(size_t size) = malloc;
+UA_EXPORT UA_THREAD_LOCAL void (*UA_freeSingleton)(void *ptr) = free;
+UA_EXPORT UA_THREAD_LOCAL void * (*UA_callocSingleton)(size_t nelem, size_t elsize) = calloc;
+UA_EXPORT UA_THREAD_LOCAL void * (*UA_reallocSingleton)(void *ptr, size_t size) = realloc;
#endif
unsigned int UA_socket_set_blocking(UA_SOCKET sockfd){
@@ -66634,7 +75275,7 @@ void UA_deinitialize_architecture_network(void){
#endif /* UA_ARCHITECTURE_POSIX */
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/arch/win32/ua_clock.c" ***********************************/
+/**** amalgamated original file "/arch/win32/ua_clock.c" ****/
/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
* See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
@@ -66683,7 +75324,11 @@ UA_Int64 UA_DateTime_localTimeUtcOffset(void) {
time_t gmt, rawtime = time(NULL);
struct tm ptm;
+#ifdef __CODEGEARC__
+ gmtime_s(&rawtime, &ptm);
+#else
gmtime_s(&ptm, &rawtime);
+#endif
// Request that mktime() looksup dst in timezone database
ptm.tm_isdst = -1;
gmt = mktime(&ptm);
@@ -66701,7 +75346,7 @@ UA_DateTime UA_DateTime_nowMonotonic(void) {
#endif /* UA_ARCHITECTURE_WIN32 */
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/arch/win32/ua_architecture_functions.c" ***********************************/
+/**** amalgamated original file "/arch/win32/ua_architecture_functions.c" ****/
/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
* See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
@@ -66712,18 +75357,26 @@ UA_DateTime UA_DateTime_nowMonotonic(void) {
#ifdef UA_ARCHITECTURE_WIN32
+/* Global malloc singletons */
+#ifdef UA_ENABLE_MALLOC_SINGLETON
+UA_EXPORT UA_THREAD_LOCAL void * (*UA_mallocSingleton)(size_t size) = malloc;
+UA_EXPORT UA_THREAD_LOCAL void (*UA_freeSingleton)(void *ptr) = free;
+UA_EXPORT UA_THREAD_LOCAL void * (*UA_callocSingleton)(size_t nelem, size_t elsize) = calloc;
+UA_EXPORT UA_THREAD_LOCAL void * (*UA_reallocSingleton)(void *ptr, size_t size) = realloc;
+#endif
+
unsigned int UA_socket_set_blocking(UA_SOCKET sockfd){
u_long iMode = 0;
if(ioctlsocket(sockfd, FIONBIO, &iMode) != NO_ERROR)
return UA_STATUSCODE_BADINTERNALERROR;
- return UA_STATUSCODE_GOOD;;
+ return UA_STATUSCODE_GOOD;
}
unsigned int UA_socket_set_nonblocking(UA_SOCKET sockfd){
u_long iMode = 1;
if(ioctlsocket(sockfd, FIONBIO, &iMode) != NO_ERROR)
return UA_STATUSCODE_BADINTERNALERROR;
- return UA_STATUSCODE_GOOD;;
+ return UA_STATUSCODE_GOOD;
}
void UA_initialize_architecture_network(void){
@@ -66737,7 +75390,7 @@ void UA_deinitialize_architecture_network(void){
#endif /* UA_ARCHITECTURE_WIN32 */
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/arch/network_tcp.c" ***********************************/
+/**** amalgamated original file "/arch/network_tcp.c" ****/
/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
* See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
@@ -66776,19 +75429,19 @@ connection_getsendbuffer(UA_Connection *connection,
static void
connection_releasesendbuffer(UA_Connection *connection,
UA_ByteString *buf) {
- UA_ByteString_deleteMembers(buf);
+ UA_ByteString_clear(buf);
}
static void
connection_releaserecvbuffer(UA_Connection *connection,
UA_ByteString *buf) {
- UA_ByteString_deleteMembers(buf);
+ UA_ByteString_clear(buf);
}
static UA_StatusCode
connection_write(UA_Connection *connection, UA_ByteString *buf) {
if(connection->state == UA_CONNECTIONSTATE_CLOSED) {
- UA_ByteString_deleteMembers(buf);
+ UA_ByteString_clear(buf);
return UA_STATUSCODE_BADCONNECTIONCLOSED;
}
@@ -66796,6 +75449,10 @@ connection_write(UA_Connection *connection, UA_ByteString *buf) {
int flags = 0;
flags |= MSG_NOSIGNAL;
+ struct pollfd poll_fd[1];
+ poll_fd[0].fd = connection->sockfd;
+ poll_fd[0].events = UA_POLLOUT;
+
/* Send the full buffer. This may require several calls to send */
size_t nWritten = 0;
do {
@@ -66805,17 +75462,24 @@ connection_write(UA_Connection *connection, UA_ByteString *buf) {
n = UA_send(connection->sockfd,
(const char*)buf->data + nWritten,
bytes_to_send, flags);
- if(n < 0 && UA_ERRNO != UA_INTERRUPTED && UA_ERRNO != UA_AGAIN) {
- connection->close(connection);
- UA_ByteString_deleteMembers(buf);
- return UA_STATUSCODE_BADCONNECTIONCLOSED;
+ if(n<0) {
+ if(UA_ERRNO != UA_INTERRUPTED && UA_ERRNO != UA_AGAIN) {
+ connection->close(connection);
+ UA_ByteString_clear(buf);
+ return UA_STATUSCODE_BADCONNECTIONCLOSED;
+ }
+ int poll_ret;
+ do {
+ poll_ret = UA_poll (poll_fd, 1, 1000);
+ } while (poll_ret == 0 || (poll_ret < 0 && UA_ERRNO == UA_INTERRUPTED));
}
} while(n < 0);
+
nWritten += (size_t)n;
} while(nWritten < buf->length);
/* Free the buffer */
- UA_ByteString_deleteMembers(buf);
+ UA_ByteString_clear(buf);
return UA_STATUSCODE_GOOD;
}
@@ -66840,7 +75504,7 @@ connection_recv(UA_Connection *connection, UA_ByteString *response,
if(resultsize == -1) {
/* The call to select was interrupted. Act as if it timed out. */
- if(UA_ERRNO == EINTR)
+ if(UA_ERRNO == UA_INTERRUPTED)
return UA_STATUSCODE_GOODNONCRITICALTIMEOUT;
/* The error cannot be recovered. Close the connection. */
@@ -66867,7 +75531,7 @@ connection_recv(UA_Connection *connection, UA_ByteString *response,
/* The remote side closed the connection */
if(ret == 0) {
if(internallyAllocated)
- UA_ByteString_deleteMembers(response);
+ UA_ByteString_clear(response);
connection->close(connection);
return UA_STATUSCODE_BADCONNECTIONCLOSED;
}
@@ -66875,7 +75539,7 @@ connection_recv(UA_Connection *connection, UA_ByteString *response,
/* Error case */
if(ret < 0) {
if(internallyAllocated)
- UA_ByteString_deleteMembers(response);
+ UA_ByteString_clear(response);
if(UA_ERRNO == UA_INTERRUPTED || (timeout > 0) ?
false : (UA_ERRNO == UA_EAGAIN || UA_ERRNO == UA_WOULDBLOCK))
return UA_STATUSCODE_GOOD; /* statuscode_good but no data -> retry */
@@ -67005,6 +75669,8 @@ ServerNetworkLayerTCP_add(UA_ServerNetworkLayer *nl, ServerNetworkLayerTCP *laye
c->state = UA_CONNECTIONSTATE_OPENING;
c->openingDate = UA_DateTime_nowMonotonic();
+ layer->connectionsSize++;
+
/* Add to the linked list */
LIST_INSERT_HEAD(&layer->connections, e, pointers);
if(nl->statistics) {
@@ -67020,8 +75686,9 @@ addServerSocket(ServerNetworkLayerTCP *layer, struct addrinfo *ai) {
UA_SOCKET newsock = UA_socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
if(newsock == UA_INVALID_SOCKET)
{
- UA_LOG_WARNING(layer->logger, UA_LOGCATEGORY_NETWORK,
- "Error opening the server socket");
+ UA_LOG_SOCKET_ERRNO_WRAP(
+ UA_LOG_WARNING(layer->logger, UA_LOGCATEGORY_NETWORK,
+ "Error opening the server socket: %s", errno_str));
return UA_STATUSCODE_BADCOMMUNICATIONERROR;
}
@@ -67058,7 +75725,36 @@ addServerSocket(ServerNetworkLayerTCP *layer, struct addrinfo *ai) {
}
/* Bind socket to address */
- if(UA_bind(newsock, ai->ai_addr, (socklen_t)ai->ai_addrlen) < 0) {
+ int ret = UA_bind(newsock, ai->ai_addr, (socklen_t)ai->ai_addrlen);
+ if(ret < 0) {
+ /* If bind to specific address failed, try to bind *-socket */
+ if(ai->ai_family == AF_INET) {
+ struct sockaddr_in *sin = (struct sockaddr_in *)ai->ai_addr;
+ if(sin->sin_addr.s_addr != htonl(INADDR_ANY)) {
+ sin->sin_addr.s_addr = 0;
+ ret = 0;
+ }
+ }
+#if UA_IPV6
+ else if(ai->ai_family == AF_INET6) {
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)ai->ai_addr;
+ if(!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
+ memset(&sin6->sin6_addr, 0, sizeof(sin6->sin6_addr));
+ sin6->sin6_scope_id = 0;
+ ret = 0;
+ }
+ }
+#endif // UA_IPV6
+ if(ret == 0) {
+ ret = UA_bind(newsock, ai->ai_addr, (socklen_t)ai->ai_addrlen);
+ if(ret == 0) {
+ /* The second bind fixed the issue, inform the user. */
+ UA_LOG_INFO(layer->logger, UA_LOGCATEGORY_NETWORK,
+ "Server socket bound to unspecified address");
+ }
+ }
+ }
+ if(ret < 0) {
UA_LOG_SOCKET_ERRNO_WRAP(
UA_LOG_WARNING(layer->logger, UA_LOGCATEGORY_NETWORK,
"Error binding a server socket: %s", errno_str));
@@ -67090,22 +75786,43 @@ addServerSocket(ServerNetworkLayerTCP *layer, struct addrinfo *ai) {
}
static UA_StatusCode
-ServerNetworkLayerTCP_start(UA_ServerNetworkLayer *nl, const UA_String *customHostname) {
- UA_initialize_architecture_network();
+ServerNetworkLayerTCP_start(UA_ServerNetworkLayer *nl, const UA_Logger *logger,
+ const UA_String *customHostname) {
+ UA_initialize_architecture_network();
ServerNetworkLayerTCP *layer = (ServerNetworkLayerTCP *)nl->handle;
+ layer->logger = logger;
/* Get addrinfo of the server and create server sockets */
+ char hostname[512];
+ if(customHostname->length) {
+ if(customHostname->length >= sizeof(hostname))
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ memcpy(hostname, customHostname->data, customHostname->length);
+ hostname[customHostname->length] = '\0';
+ }
char portno[6];
UA_snprintf(portno, 6, "%d", layer->port);
struct addrinfo hints, *res;
memset(&hints, 0, sizeof hints);
- hints.ai_family = AF_UNSPEC;
+#if UA_IPV6
+ hints.ai_family = AF_UNSPEC; /* allow IPv4 and IPv6 */
+#else
+ hints.ai_family = AF_INET; /* enforce IPv4 only */
+#endif
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
+#ifdef AI_ADDRCONFIG
+ hints.ai_flags |= AI_ADDRCONFIG;
+#endif
hints.ai_protocol = IPPROTO_TCP;
- if(UA_getaddrinfo(NULL, portno, &hints, &res) != 0)
+ int retcode = UA_getaddrinfo(customHostname->length ? hostname : NULL,
+ portno, &hints, &res);
+ if(retcode != 0) {
+ UA_LOG_SOCKET_ERRNO_GAI_WRAP(UA_LOG_WARNING(layer->logger, UA_LOGCATEGORY_NETWORK,
+ "getaddrinfo lookup of %s failed with error %d - %s", hostname, retcode, errno_str));
return UA_STATUSCODE_BADINTERNALERROR;
+ }
/* There might be serveral addrinfos (for different network cards,
* IPv4/IPv6). Add a server socket for all of them. */
@@ -67113,12 +75830,13 @@ ServerNetworkLayerTCP_start(UA_ServerNetworkLayer *nl, const UA_String *customHo
for(layer->serverSocketsSize = 0;
layer->serverSocketsSize < FD_SETSIZE && ai != NULL;
ai = ai->ai_next) {
- UA_StatusCode statusCode = addServerSocket(layer, ai);
- if(statusCode != UA_STATUSCODE_GOOD)
- return statusCode;
-
+ addServerSocket(layer, ai);
}
UA_freeaddrinfo(res);
+
+ if(layer->serverSocketsSize == 0) {
+ return UA_STATUSCODE_BADCOMMUNICATIONERROR;
+ }
/* Get the discovery url from the hostname */
UA_String du = UA_STRING_NULL;
@@ -67197,7 +75915,7 @@ ServerNetworkLayerTCP_listen(UA_ServerNetworkLayer *nl, UA_Server *server,
struct sockaddr_storage remote;
socklen_t remote_size = sizeof(remote);
- UA_SOCKET newsockfd = UA_accept((UA_SOCKET)layer->serverSockets[i],
+ UA_SOCKET newsockfd = UA_accept(layer->serverSockets[i],
(struct sockaddr*)&remote, &remote_size);
if(newsockfd == UA_INVALID_SOCKET)
continue;
@@ -67225,7 +75943,7 @@ ServerNetworkLayerTCP_listen(UA_ServerNetworkLayer *nl, UA_Server *server,
UA_close(e->connection.sockfd);
UA_Server_removeConnection(server, &e->connection);
if(nl->statistics) {
- nl->statistics->connectionTimeoutCount--;
+ nl->statistics->connectionTimeoutCount++;
nl->statistics->currentConnectionCount--;
}
continue;
@@ -67290,9 +76008,9 @@ ServerNetworkLayerTCP_stop(UA_ServerNetworkLayer *nl, UA_Server *server) {
/* run only when the server is stopped */
static void
-ServerNetworkLayerTCP_deleteMembers(UA_ServerNetworkLayer *nl) {
+ServerNetworkLayerTCP_clear(UA_ServerNetworkLayer *nl) {
ServerNetworkLayerTCP *layer = (ServerNetworkLayerTCP *)nl->handle;
- UA_String_deleteMembers(&nl->discoveryUrl);
+ UA_String_clear(&nl->discoveryUrl);
/* Hard-close and remove remaining connections. The server is no longer
* running. So this is safe. */
@@ -67313,10 +76031,10 @@ ServerNetworkLayerTCP_deleteMembers(UA_ServerNetworkLayer *nl) {
UA_ServerNetworkLayer
UA_ServerNetworkLayerTCP(UA_ConnectionConfig config, UA_UInt16 port,
- UA_UInt16 maxConnections, UA_Logger *logger) {
+ UA_UInt16 maxConnections) {
UA_ServerNetworkLayer nl;
memset(&nl, 0, sizeof(UA_ServerNetworkLayer));
- nl.clear = ServerNetworkLayerTCP_deleteMembers;
+ nl.clear = ServerNetworkLayerTCP_clear;
nl.localConnectionConfig = config;
nl.start = ServerNetworkLayerTCP_start;
nl.listen = ServerNetworkLayerTCP_listen;
@@ -67329,7 +76047,6 @@ UA_ServerNetworkLayerTCP(UA_ConnectionConfig config, UA_UInt16 port,
return nl;
nl.handle = layer;
- layer->logger = logger;
layer->port = port;
layer->maxConnections = maxConnections;
@@ -67363,7 +76080,7 @@ static void
ClientNetworkLayerTCP_free(UA_Connection *connection) {
if(!connection->handle)
return;
-
+
TCPClientConnection *tcpConnection = (TCPClientConnection *)connection->handle;
if(tcpConnection->server)
UA_freeaddrinfo(tcpConnection->server);
@@ -67373,158 +76090,186 @@ ClientNetworkLayerTCP_free(UA_Connection *connection) {
}
UA_StatusCode
-UA_ClientConnectionTCP_poll(UA_Client *client, void *data, UA_UInt32 timeout) {
- UA_Connection *connection = (UA_Connection*) data;
+UA_ClientConnectionTCP_poll(UA_Connection *connection, UA_UInt32 timeout,
+ const UA_Logger *logger) {
if(connection->state == UA_CONNECTIONSTATE_CLOSED)
return UA_STATUSCODE_BADDISCONNECT;
if(connection->state == UA_CONNECTIONSTATE_ESTABLISHED)
return UA_STATUSCODE_GOOD;
- TCPClientConnection *tcpConnection = (TCPClientConnection*) connection->handle;
- UA_SOCKET clientsockfd = connection->sockfd;
- UA_ClientConfig *config = UA_Client_getConfig(client);
-
/* Connection timeout? */
+ TCPClientConnection *tcpConnection = (TCPClientConnection*) connection->handle;
if((UA_Double) (UA_DateTime_nowMonotonic() - tcpConnection->connStart)
- > tcpConnection->timeout * UA_DATETIME_MSEC ) {
+ > (UA_Double) tcpConnection->timeout * UA_DATETIME_MSEC ) {
+ UA_LOG_WARNING(logger, UA_LOGCATEGORY_NETWORK, "Timed out");
ClientNetworkLayerTCP_close(connection);
- UA_LOG_WARNING(&config->logger, UA_LOGCATEGORY_NETWORK, "Timed out");
return UA_STATUSCODE_BADDISCONNECT;
}
- /* On linux connect may immediately return with ECONNREFUSED but we still
- * want to try to connect. Thus use a loop and retry until timeout is
- * reached */
+ /* Get a socket and connect (only once) if not already done in a previous
+ * call. On win32, calling connect multiple times is not recommended on
+ * non-blocking sockets
+ * (https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-connect).
+ * On posix it is also not necessary to call connect multiple times.
+ *
+ * Identification of successfull connection is done using select (writeable/errorfd)
+ * and getsockopt using SO_ERROR on win32 and posix.
+ */
+ if(connection->sockfd == UA_INVALID_SOCKET) {
+ connection->sockfd = UA_socket(tcpConnection->server->ai_family,
+ tcpConnection->server->ai_socktype,
+ tcpConnection->server->ai_protocol);
+ if(connection->sockfd == UA_INVALID_SOCKET) {
+ UA_LOG_WARNING(logger, UA_LOGCATEGORY_NETWORK,
+ "Could not create client socket: %s", strerror(UA_ERRNO));
+ ClientNetworkLayerTCP_close(connection);
+ return UA_STATUSCODE_BADDISCONNECT;
+ }
- /* Get a socket */
- if(clientsockfd <= 0) {
- clientsockfd = UA_socket(tcpConnection->server->ai_family,
- tcpConnection->server->ai_socktype,
- tcpConnection->server->ai_protocol);
- connection->sockfd = (UA_Int32)clientsockfd; /* cast for win32 */
- }
+ /* Non blocking connect to be able to timeout */
+ if(UA_socket_set_nonblocking(connection->sockfd) != UA_STATUSCODE_GOOD) {
+ UA_LOG_WARNING(logger, UA_LOGCATEGORY_NETWORK,
+ "Could not set the client socket to nonblocking");
+ ClientNetworkLayerTCP_close(connection);
+ return UA_STATUSCODE_BADDISCONNECT;
+ }
- if(clientsockfd == UA_INVALID_SOCKET) {
- UA_LOG_WARNING(&config->logger, UA_LOGCATEGORY_NETWORK,
- "Could not create client socket: %s", strerror(UA_ERRNO));
- ClientNetworkLayerTCP_close(connection);
- return UA_STATUSCODE_BADDISCONNECT;
- }
+ /* Don't have the socket create interrupt signals */
+#ifdef SO_NOSIGPIPE
+ int val = 1;
+ int sso_result = setsockopt(connection->sockfd, SOL_SOCKET, SO_NOSIGPIPE,
+ (void *)&val, sizeof(val));
+ if(sso_result < 0)
+ UA_LOG_WARNING(logger, UA_LOGCATEGORY_NETWORK, "Couldn't set SO_NOSIGPIPE");
+#endif
+ int error = UA_connect(connection->sockfd, tcpConnection->server->ai_addr,
+ tcpConnection->server->ai_addrlen);
- /* Non blocking connect to be able to timeout */
- if(UA_socket_set_nonblocking(clientsockfd) != UA_STATUSCODE_GOOD) {
- UA_LOG_WARNING(&config->logger, UA_LOGCATEGORY_NETWORK,
- "Could not set the client socket to nonblocking");
- ClientNetworkLayerTCP_close(connection);
- return UA_STATUSCODE_BADDISCONNECT;
+ /* Connection successful */
+ if(error == 0) {
+ connection->state = UA_CONNECTIONSTATE_ESTABLISHED;
+ return UA_STATUSCODE_GOOD;
+ }
+
+ /* The connection failed */
+ if((UA_ERRNO != UA_ERR_CONNECTION_PROGRESS)) {
+ UA_LOG_WARNING(logger, UA_LOGCATEGORY_NETWORK,
+ "Connection to %.*s failed with error: %s",
+ (int)tcpConnection->endpointUrl.length,
+ tcpConnection->endpointUrl.data, strerror(UA_ERRNO));
+ ClientNetworkLayerTCP_close(connection);
+ return UA_STATUSCODE_BADDISCONNECT;
+ }
}
- /* Non blocking connect */
- int error = UA_connect(clientsockfd, tcpConnection->server->ai_addr,
- tcpConnection->server->ai_addrlen);
+ /* Use select to wait until connected. Return with a half-opened connection
+ * after a timeout. */
+ UA_UInt32 timeout_usec = timeout * 1000;
- if((error == -1) && (UA_ERRNO != UA_ERR_CONNECTION_PROGRESS)) {
- ClientNetworkLayerTCP_close(connection);
- UA_LOG_WARNING(&config->logger, UA_LOGCATEGORY_NETWORK,
+#ifdef _OS9000
+ /* OS-9 cannot use select for checking write sockets. Therefore, we need to
+ * use connect until success or failed */
+ int resultsize = 0;
+ do {
+ u_int32 time = 0x80000001;
+ signal_code sig;
+
+ timeout_usec -= 1000000/256; // Sleep 1/256 second
+ if(timeout_usec < 0)
+ break;
+
+ _os_sleep(&time, &sig);
+ error = connect(connection->sockfd, tcpConnection->server->ai_addr,
+ tcpConnection->server->ai_addrlen);
+ if((error == -1 && UA_ERRNO == EISCONN) || (error == 0))
+ resultsize = 1;
+ if(error == -1 && UA_ERRNO != EALREADY && UA_ERRNO != EINPROGRESS)
+ break;
+ } while(resultsize == 0);
+#else
+ /* Wait in a select-call until the connection fully opens or the timeout
+ * happens */
+
+ /* On windows select both writing and error fdset */
+ fd_set writing_fdset;
+ FD_ZERO(&writing_fdset);
+ UA_fd_set(connection->sockfd, &writing_fdset);
+ fd_set error_fdset;
+ FD_ZERO(&error_fdset);
+#ifdef _WIN32
+ UA_fd_set(connection->sockfd, &error_fdset);
+#endif
+ struct timeval tmptv = {(long int)(timeout_usec / 1000000),
+ (int)(timeout_usec % 1000000)};
+
+ int ret = UA_select((UA_Int32)(connection->sockfd + 1), NULL, &writing_fdset,
+ &error_fdset, &tmptv);
+
+ // When select fails abort connection
+ if(ret == -1) {
+ UA_LOG_WARNING(logger, UA_LOGCATEGORY_NETWORK,
"Connection to %.*s failed with error: %s",
(int)tcpConnection->endpointUrl.length,
tcpConnection->endpointUrl.data, strerror(UA_ERRNO));
+ ClientNetworkLayerTCP_close(connection);
return UA_STATUSCODE_BADDISCONNECT;
+ } else if (timeout && ret == 0) {
+ UA_LOG_WARNING(logger, UA_LOGCATEGORY_NETWORK,
+ "Connection to %.*s timed out",
+ (int)tcpConnection->endpointUrl.length,
+ tcpConnection->endpointUrl.data);
+ ClientNetworkLayerTCP_close(connection);
+ return UA_STATUSCODE_BADTIMEOUT;
}
- /* Use select to wait and check if connected */
- if(error == -1 && (UA_ERRNO == UA_ERR_CONNECTION_PROGRESS)) {
- /* connection in progress. Wait until connected using select */
- UA_UInt32 timeout_usec = timeout * 1000;
-
-#ifdef _OS9000
- /* OS-9 can't use select for checking write sockets.
- * Therefore, we need to use connect until success or failed */
- int resultsize = 0;
- do {
- u_int32 time = 0x80000001;
- signal_code sig;
-
- timeout_usec -= 1000000/256; // Sleep 1/256 second
- if(timeout_usec < 0)
- break;
+ int resultsize = UA_fd_isset(connection->sockfd, &writing_fdset);
+#endif
- _os_sleep(&time,&sig);
- error = connect(clientsockfd, tcpConnection->server->ai_addr,
- tcpConnection->server->ai_addrlen);
- if((error == -1 && UA_ERRNO == EISCONN) || (error == 0))
- resultsize = 1;
- if(error == -1 && UA_ERRNO != EALREADY && UA_ERRNO != EINPROGRESS)
- break;
- } while(resultsize == 0);
+ /* Any errors on the socket reported? */
+ OPTVAL_TYPE so_error = 0;
+ socklen_t len = sizeof(so_error);
+ ret = UA_getsockopt(connection->sockfd, SOL_SOCKET, SO_ERROR, &so_error, &len);
+ if(ret != 0 || so_error != 0) {
+ // UA_LOG_SOCKET_ERRNO_GAI_WRAP because of so_error
+#ifndef _WIN32
+ char *errno_str = strerror(ret == 0 ? so_error : UA_ERRNO);
#else
- fd_set fdset;
- FD_ZERO(&fdset);
- UA_fd_set(clientsockfd, &fdset);
- struct timeval tmptv = { (long int) (timeout_usec / 1000000),
- (int) (timeout_usec % 1000000) };
- int resultsize = UA_select((UA_Int32) (clientsockfd + 1), NULL, &fdset, NULL, &tmptv);
+ char *errno_str = NULL;
+ FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL, ret == 0 ? so_error : WSAGetLastError(),
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&errno_str, 0,
+ NULL);
#endif
- if(resultsize == 1) {
- /* Windows does not have any getsockopt equivalent and it is not needed there */
+ UA_LOG_WARNING(logger, UA_LOGCATEGORY_NETWORK,
+ "Connection to %.*s failed with error: %s",
+ (int)tcpConnection->endpointUrl.length,
+ tcpConnection->endpointUrl.data, errno_str);
#ifdef _WIN32
- connection->sockfd = clientsockfd;
- connection->state = UA_CONNECTIONSTATE_ESTABLISHED;
- return UA_STATUSCODE_GOOD;
-#else
- OPTVAL_TYPE so_error;
- socklen_t len = sizeof so_error;
- int ret = UA_getsockopt(clientsockfd, SOL_SOCKET, SO_ERROR, &so_error, &len);
-
- if(ret == 0 && so_error == 0) {
- /* Connected */
- connection->state = UA_CONNECTIONSTATE_ESTABLISHED;
- return UA_STATUSCODE_GOOD;
- } else {
- if(so_error != ECONNREFUSED) {
- /* General error */
- ClientNetworkLayerTCP_close(connection);
- UA_LOG_WARNING(&config->logger, UA_LOGCATEGORY_NETWORK,
- "Connection to %.*s failed with error: %s",
- (int)tcpConnection->endpointUrl.length,
- tcpConnection->endpointUrl.data,
- strerror(ret == 0 ? so_error : UA_ERRNO));
- return UA_STATUSCODE_BADDISCONNECT;
- }
-
- /* On connection refused we should still try to connect.
- * Connection refused happens on localhost or local ip without
- * timeout. Wait until we try a again. Do not make this too
- * small, otherwise the timeout is somehow wrong */
- }
+ LocalFree(errno_str);
#endif
- }
- } else {
- connection->state = UA_CONNECTIONSTATE_ESTABLISHED;
- return UA_STATUSCODE_GOOD;
+ ClientNetworkLayerTCP_close(connection);
+ return UA_STATUSCODE_BADDISCONNECT;
}
-#ifdef SO_NOSIGPIPE
- int val = 1;
- int sso_result = setsockopt(connection->sockfd, SOL_SOCKET,
- SO_NOSIGPIPE, (void*)&val, sizeof(val));
- if(sso_result < 0)
- UA_LOG_WARNING(&config->logger, UA_LOGCATEGORY_NETWORK,
- "Couldn't set SO_NOSIGPIPE");
-#endif
+ /* The connection is fully opened. Otherwise, select has timed out. But we
+ * can retry. */
+ if(resultsize > 0)
+ connection->state = UA_CONNECTIONSTATE_ESTABLISHED;
return UA_STATUSCODE_GOOD;
}
UA_Connection
UA_ClientConnectionTCP_init(UA_ConnectionConfig config, const UA_String endpointUrl,
- UA_UInt32 timeout, UA_Logger *logger) {
+ UA_UInt32 timeout, const UA_Logger *logger) {
UA_initialize_architecture_network();
UA_Connection connection;
memset(&connection, 0, sizeof(UA_Connection));
connection.state = UA_CONNECTIONSTATE_OPENING;
+ connection.sockfd = UA_INVALID_SOCKET;
connection.send = connection_write;
connection.recv = connection_recv;
connection.close = ClientNetworkLayerTCP_close;
@@ -67535,6 +76280,10 @@ UA_ClientConnectionTCP_init(UA_ConnectionConfig config, const UA_String endpoint
TCPClientConnection *tcpClientConnection = (TCPClientConnection*)
UA_malloc(sizeof(TCPClientConnection));
+ if(!tcpClientConnection) {
+ connection.state = UA_CONNECTIONSTATE_CLOSED;
+ return connection;
+ }
memset(tcpClientConnection, 0, sizeof(TCPClientConnection));
connection.handle = (void*) tcpClientConnection;
tcpClientConnection->timeout = timeout;
@@ -67569,227 +76318,15 @@ UA_ClientConnectionTCP_init(UA_ConnectionConfig config, const UA_String endpoint
char portStr[6];
UA_snprintf(portStr, 6, "%d", port);
int error = UA_getaddrinfo(hostname, portStr, &tcpClientConnection->hints,
- &tcpClientConnection->server);
+ &tcpClientConnection->server);
if(error != 0 || !tcpClientConnection->server) {
UA_LOG_SOCKET_ERRNO_GAI_WRAP(UA_LOG_WARNING(logger, UA_LOGCATEGORY_NETWORK,
- "DNS lookup of %s failed with error %s",
- hostname, errno_str));
+ "DNS lookup of %s failed with error %d - %s",
+ hostname, error, errno_str));
connection.state = UA_CONNECTIONSTATE_CLOSED;
return connection;
}
- return connection;
-}
-
-UA_Connection
-UA_ClientConnectionTCP(UA_ConnectionConfig config, const UA_String endpointUrl,
- UA_UInt32 timeout, UA_Logger *logger) {
- UA_initialize_architecture_network();
-
- UA_Connection connection;
- memset(&connection, 0, sizeof(UA_Connection));
- connection.state = UA_CONNECTIONSTATE_CLOSED;
- connection.send = connection_write;
- connection.recv = connection_recv;
- connection.close = ClientNetworkLayerTCP_close;
- connection.free = ClientNetworkLayerTCP_free;
- connection.getSendBuffer = connection_getsendbuffer;
- connection.releaseSendBuffer = connection_releasesendbuffer;
- connection.releaseRecvBuffer = connection_releaserecvbuffer;
- connection.handle = NULL;
-
- UA_String hostnameString = UA_STRING_NULL;
- UA_String pathString = UA_STRING_NULL;
- UA_UInt16 port = 0;
- char hostname[512];
-
- UA_StatusCode parse_retval =
- UA_parseEndpointUrl(&endpointUrl, &hostnameString, &port, &pathString);
- if(parse_retval != UA_STATUSCODE_GOOD || hostnameString.length > 511) {
- UA_LOG_WARNING(logger, UA_LOGCATEGORY_NETWORK,
- "Server url is invalid: %.*s",
- (int)endpointUrl.length, endpointUrl.data);
- return connection;
- }
- memcpy(hostname, hostnameString.data, hostnameString.length);
- hostname[hostnameString.length] = 0;
-
- if(port == 0) {
- port = 4840;
- UA_LOG_INFO(logger, UA_LOGCATEGORY_NETWORK,
- "No port defined, using default port %" PRIu16, port);
- }
-
- struct addrinfo hints, *server;
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = AF_UNSPEC;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_protocol = IPPROTO_TCP;
- char portStr[6];
- UA_snprintf(portStr, 6, "%d", port);
- int error = UA_getaddrinfo(hostname, portStr, &hints, &server);
- if(error != 0 || !server) {
- UA_LOG_SOCKET_ERRNO_GAI_WRAP(UA_LOG_WARNING(logger, UA_LOGCATEGORY_NETWORK,
- "DNS lookup of %s failed with error %s", hostname, errno_str));
- return connection;
- }
-
- UA_Boolean connected = false;
- UA_DateTime dtTimeout = timeout * UA_DATETIME_MSEC;
- UA_DateTime connStart = UA_DateTime_nowMonotonic();
- UA_SOCKET clientsockfd;
-
- /* On linux connect may immediately return with ECONNREFUSED but we still
- * want to try to connect. So use a loop and retry until timeout is
- * reached. */
- do {
- /* Get a socket */
- clientsockfd = UA_socket(server->ai_family,
- server->ai_socktype,
- server->ai_protocol);
- if(clientsockfd == UA_INVALID_SOCKET) {
- UA_LOG_SOCKET_ERRNO_WRAP(UA_LOG_WARNING(logger, UA_LOGCATEGORY_NETWORK,
- "Could not create client socket: %s", errno_str));
- UA_freeaddrinfo(server);
- return connection;
- }
-
- connection.state = UA_CONNECTIONSTATE_OPENING;
-
- /* Connect to the server */
- connection.sockfd = clientsockfd;
-
- /* Non blocking connect to be able to timeout */
- if(UA_socket_set_nonblocking(clientsockfd) != UA_STATUSCODE_GOOD) {
- UA_LOG_WARNING(logger, UA_LOGCATEGORY_NETWORK,
- "Could not set the client socket to nonblocking");
- ClientNetworkLayerTCP_close(&connection);
- UA_freeaddrinfo(server);
- return connection;
- }
-
- /* Non blocking connect */
- error = UA_connect(clientsockfd, server->ai_addr, (socklen_t)server->ai_addrlen);
-
- if((error == -1) && (UA_ERRNO != UA_ERR_CONNECTION_PROGRESS)) {
- ClientNetworkLayerTCP_close(&connection);
- UA_LOG_SOCKET_ERRNO_WRAP(
- UA_LOG_WARNING(logger, UA_LOGCATEGORY_NETWORK,
- "Connection to %.*s failed with error: %s",
- (int)endpointUrl.length, endpointUrl.data, errno_str));
- UA_freeaddrinfo(server);
- return connection;
- }
-
- /* Use select to wait and check if connected */
- if(error == -1 && (UA_ERRNO == UA_ERR_CONNECTION_PROGRESS)) {
- /* connection in progress. Wait until connected using select */
- UA_DateTime timeSinceStart = UA_DateTime_nowMonotonic() - connStart;
- if(timeSinceStart > dtTimeout)
- break;
-
-#ifdef _OS9000
- /* OS-9 can't use select for checking write sockets.
- * Therefore, we need to use connect until success or failed
- */
- UA_DateTime timeout_usec = (dtTimeout - timeSinceStart) / UA_DATETIME_USEC;
- int resultsize = 0;
- do {
- u_int32 time = 0x80000001;
- signal_code sig;
-
- timeout_usec -= 1000000/256; // Sleep 1/256 second
- if(timeout_usec < 0)
- break;
-
- _os_sleep(&time,&sig);
- error = connect(clientsockfd, server->ai_addr, server->ai_addrlen);
- if((error == -1 && UA_ERRNO == EISCONN) || (error == 0))
- resultsize = 1;
- if(error == -1 && UA_ERRNO != EALREADY && UA_ERRNO != EINPROGRESS)
- break;
- }
- while(resultsize == 0);
-#else
- fd_set fdset;
- FD_ZERO(&fdset);
- UA_fd_set(clientsockfd, &fdset);
- UA_DateTime timeout_usec = (dtTimeout - timeSinceStart) / UA_DATETIME_USEC;
- struct timeval tmptv = {(long int) (timeout_usec / 1000000),
- (int) (timeout_usec % 1000000)};
-
- int resultsize = UA_select((UA_Int32)(clientsockfd + 1), NULL, &fdset, NULL, &tmptv);
-#endif
-
- if(resultsize == 1) {
-#ifdef _WIN32
- /* Windows does not have any getsockopt equivalent and it is not
- * needed there */
- connected = true;
- break;
-#else
- OPTVAL_TYPE so_error;
- socklen_t len = sizeof so_error;
-
- int ret = UA_getsockopt(clientsockfd, SOL_SOCKET, SO_ERROR, &so_error, &len);
-
- if(ret != 0 || so_error != 0) {
- /* on connection refused we should still try to connect */
- /* connection refused happens on localhost or local ip without timeout */
- if(so_error != ECONNREFUSED) {
- ClientNetworkLayerTCP_close(&connection);
- UA_LOG_WARNING(logger, UA_LOGCATEGORY_NETWORK,
- "Connection to %.*s failed with error: %s",
- (int)endpointUrl.length, endpointUrl.data,
- strerror(ret == 0 ? so_error : UA_ERRNO));
- UA_freeaddrinfo(server);
- return connection;
- }
- /* wait until we try a again. Do not make this too small, otherwise the
- * timeout is somehow wrong */
- UA_sleep_ms(100);
- } else {
- connected = true;
- break;
- }
-#endif
- }
- } else {
- connected = true;
- break;
- }
- ClientNetworkLayerTCP_close(&connection);
-
- } while ((UA_DateTime_nowMonotonic() - connStart) < dtTimeout);
-
- UA_freeaddrinfo(server);
-
- if(!connected) {
- /* connection timeout */
- if(connection.state != UA_CONNECTIONSTATE_CLOSED)
- ClientNetworkLayerTCP_close(&connection);
- UA_LOG_WARNING(logger, UA_LOGCATEGORY_NETWORK,
- "Trying to connect to %.*s timed out",
- (int)endpointUrl.length, endpointUrl.data);
- return connection;
- }
-
-
- /* We are connected. Reset socket to blocking */
- if(UA_socket_set_blocking(clientsockfd) != UA_STATUSCODE_GOOD) {
- UA_LOG_WARNING(logger, UA_LOGCATEGORY_NETWORK,
- "Could not set the client socket to blocking");
- ClientNetworkLayerTCP_close(&connection);
- return connection;
- }
-
-#ifdef SO_NOSIGPIPE
- int val = 1;
- int sso_result = UA_setsockopt(connection.sockfd, SOL_SOCKET,
- SO_NOSIGPIPE, (void*)&val, sizeof(val));
- if(sso_result < 0)
- UA_LOG_WARNING(logger, UA_LOGCATEGORY_NETWORK,
- "Couldn't set SO_NOSIGPIPE");
-#endif
+ /* Return connection with state UA_CONNECTIONSTATE_OPENING */
return connection;
}
diff --git a/src/3rdparty/open62541/open62541.h b/src/3rdparty/open62541/open62541.h
index 5d96866..185fa6d 100644
--- a/src/3rdparty/open62541/open62541.h
+++ b/src/3rdparty/open62541/open62541.h
@@ -1,10 +1,10 @@
/* THIS IS A SINGLE-FILE DISTRIBUTION CONCATENATED FROM THE OPEN62541 SOURCES
* visit http://open62541.org/ for information about this software
- * Git-Revision: v1.1.2-8-ge941fc23
+ * Git-Revision: v1.3.3
*/
/*
- * Copyright (C) 2014-2018 the contributors as stated in the AUTHORS file
+ * Copyright (C) 2014-2021 the contributors as stated in the AUTHORS file
*
* This file is part of open62541. open62541 is free software: you can
* redistribute it and/or modify it under the terms of the Mozilla Public
@@ -18,7 +18,7 @@
#ifndef OPEN62541_H_
#define OPEN62541_H_
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/build/src_generated/open62541/config.h" ***********************************/
+/**** amalgamated original file "/build/src_generated/open62541/config.h" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -29,10 +29,11 @@
* open62541 Version
* ----------------- */
#define UA_OPEN62541_VER_MAJOR 1
-#define UA_OPEN62541_VER_MINOR 1
-#define UA_OPEN62541_VER_PATCH 2
-#define UA_OPEN62541_VER_LABEL "-8-ge941fc23" /* Release candidate label, etc. */
-#define UA_OPEN62541_VER_COMMIT "v1.1.2-8-ge941fc23"
+#define UA_OPEN62541_VER_MINOR 3
+#define UA_OPEN62541_VER_PATCH 3
+#define UA_OPEN62541_VER_LABEL "" /* Release candidate label, etc. */
+#define UA_OPEN62541_VER_COMMIT "v1.3.3"
+#define UA_OPEN62541_VERSION "v1.3.3"
/**
* Feature Options
@@ -47,31 +48,35 @@
#define UA_ENABLE_NODEMANAGEMENT
#define UA_ENABLE_SUBSCRIPTIONS
/* #undef UA_ENABLE_PUBSUB */
+/* #undef UA_ENABLE_PUBSUB_ENCRYPTION */
+/* #undef UA_ENABLE_PUBSUB_FILE_CONFIG */
/* #undef UA_ENABLE_PUBSUB_ETH_UADP */
-/* #undef UA_ENABLE_PUBSUB_ETH_UADP_ETF */
-/* #undef UA_ENABLE_PUBSUB_ETH_UADP_XDP */
/* #undef UA_ENABLE_PUBSUB_DELTAFRAMES */
/* #undef UA_ENABLE_PUBSUB_INFORMATIONMODEL */
/* #undef UA_ENABLE_PUBSUB_INFORMATIONMODEL_METHODS */
#define UA_ENABLE_DA
-/* #undef UA_ENABLE_ENCRYPTION */
+/* #undef UA_ENABLE_DIAGNOSTICS */
#define UA_ENABLE_HISTORIZING
#define UA_ENABLE_PARSING
-/* #undef UA_ENABLE_MICRO_EMB_DEV_PROFILE */
#define UA_ENABLE_EXPERIMENTAL_HISTORIZING
#define UA_ENABLE_SUBSCRIPTIONS_EVENTS
/* #undef UA_ENABLE_JSON_ENCODING */
/* #undef UA_ENABLE_PUBSUB_MQTT */
+/* #undef UA_ENABLE_MQTT_TLS */
+/* #undef UA_ENABLE_MQTT_TLS_OPENSSL */
+/* #undef UA_ENABLE_MQTT_TLS_MBEDTLS */
/* #undef UA_ENABLE_ENCRYPTION_MBEDTLS */
+/* #undef UA_ENABLE_TPM2_SECURITY */
/* #undef UA_ENABLE_ENCRYPTION_OPENSSL */
+/* #undef UA_ENABLE_ENCRYPTION_LIBRESSL */
+#if defined(UA_ENABLE_ENCRYPTION_MBEDTLS) || defined(UA_ENABLE_ENCRYPTION_OPENSSL) || defined(UA_ENABLE_ENCRYPTION_LIBRESSL)
+#define UA_ENABLE_ENCRYPTION
+#endif
/* #undef UA_ENABLE_SUBSCRIPTIONS_ALARMS_CONDITIONS */
/* Multithreading */
/* #undef UA_ENABLE_IMMUTABLE_NODES */
#define UA_MULTITHREADING 0
-#if UA_MULTITHREADING >= 200 && !defined(UA_ENABLE_IMMUTABLE_NODES)
-#error "The multithreading feature requires nodes to be immutable"
-#endif
/* Advanced Options */
#define UA_ENABLE_STATUSCODE_DESCRIPTIONS
@@ -88,14 +93,16 @@
/* #undef UA_ENABLE_VALGRIND_INTERACTIVE */
#define UA_VALGRIND_INTERACTIVE_INTERVAL 1000
#define UA_GENERATED_NAMESPACE_ZERO
-/* #undef UA_ENABLE_PUBSUB_CUSTOM_PUBLISH_HANDLING */
+/* #undef UA_GENERATED_NAMESPACE_ZERO_FULL */
+/* #undef UA_ENABLE_PUBSUB_MONITORING */
+/* #undef UA_ENABLE_PUBSUB_BUFMALLOC */
/* #undef UA_PACK_DEBIAN */
/* Options for Debugging */
#define UA_DEBUG
/* #undef UA_DEBUG_DUMP_PKGS */
-
+/* #undef UA_DEBUG_FILE_LINE_INFO */
/**
* Function Export
* ---------------
@@ -129,517 +136,31 @@
# endif
#endif
-// specific architectures can undef this
-#define UA_HAS_GETIFADDR
-
-
-
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/include/open62541/architecture_base.h" ***********************************/
-
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- *
- * Copyright 2018 (c) Stefan Profanter, fortiss GmbH
- */
-
-#ifndef ARCH_UA_ARCHITECTURE_BASE_H
-#define ARCH_UA_ARCHITECTURE_BASE_H
-
-/*
- * With the following list of defines, one can define its own UA_sleep_ms using a preprocessor define.
- * E.g. see unit tests.
- */
-
-#ifdef UA_sleep_ms
-void UA_sleep_ms(unsigned long ms);
-#endif
-
-#ifdef UA_malloc
-void* UA_malloc(unsigned long size);
-#endif
-
-#ifdef UA_calloc
-void* UA_calloc(unsigned long num, unsigned long size); //allocate memory in the heap with size*num bytes and set the memory to zero
-#endif
-
-#ifdef UA_realloc
-void* UA_realloc(void *ptr, unsigned long new_size);//re-allocate memory in the heap with new_size bytes from previously allocated memory ptr
-#endif
-
-#ifdef UA_free
-void UA_free(void* ptr); //de-allocate memory previously allocated with UA_malloc, UA_calloc or UA_realloc
-#endif
-
-#endif //ARCH_UA_ARCHITECTURE_BASE_H
-
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/arch/win32/ua_architecture.h" ***********************************/
-
-/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
- * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
- *
- * Copyright 2016-2017 (c) Julius Pfrommer, Fraunhofer IOSB
- * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
- */
-
-#ifdef UA_ARCHITECTURE_WIN32
-
-#ifndef PLUGINS_ARCH_WIN32_UA_ARCHITECTURE_H_
-#define PLUGINS_ARCH_WIN32_UA_ARCHITECTURE_H_
-
-
-#ifndef _BSD_SOURCE
-# define _BSD_SOURCE
-#endif
-
-/* Disable some security warnings on MSVC */
-#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
-# define _CRT_SECURE_NO_WARNINGS
-#endif
-
-/* Assume that Windows versions are newer than Windows XP */
-#if defined(__MINGW32__) && (!defined(WINVER) || WINVER < 0x501)
-# undef WINVER
-# undef _WIN32_WINDOWS
-# undef _WIN32_WINNT
-# define WINVER 0x0600
-# define _WIN32_WINDOWS 0x0600
-# define _WIN32_WINNT 0x0600 //windows vista version, which included InepPton
-#endif
-
-#include <stdlib.h>
-#if defined(_WIN32) && !defined(__clang__)
-# include <malloc.h>
-#endif
-
-#include <stdio.h>
-#include <errno.h>
-#include <winsock2.h>
-#include <windows.h>
-#include <ws2tcpip.h>
-
-#if defined (_MSC_VER) || defined(__clang__)
-# ifndef UNDER_CE
-# include <io.h> //access
-# define UA_access _access
-# endif
-#else
-# include <unistd.h> //access and tests
-# define UA_access access
-#endif
-
-#define ssize_t int
-#define OPTVAL_TYPE char
-#ifndef UA_sleep_ms
-# define UA_sleep_ms(X) Sleep(X)
-#endif
-
-// Windows does not support ansi colors
-// #define UA_ENABLE_LOG_COLORS
-
-#define UA_IPV6 1
-
-#if defined(__MINGW32__) && !defined(__clang__) //mingw defines SOCKET as long long unsigned int, giving errors in logging and when comparing with UA_Int32
-# define UA_SOCKET int
-# define UA_INVALID_SOCKET -1
-#else
-# define UA_SOCKET SOCKET
-# define UA_INVALID_SOCKET INVALID_SOCKET
-#endif
-#define UA_ERRNO WSAGetLastError()
-#define UA_INTERRUPTED WSAEINTR
-#define UA_AGAIN WSAEWOULDBLOCK
-#define UA_EAGAIN EAGAIN
-#define UA_WOULDBLOCK WSAEWOULDBLOCK
-#define UA_ERR_CONNECTION_PROGRESS WSAEWOULDBLOCK
-
-#define UA_fd_set(fd, fds) FD_SET((UA_SOCKET)fd, fds)
-#define UA_fd_isset(fd, fds) FD_ISSET((UA_SOCKET)fd, fds)
-
-#ifdef UNDER_CE
-# define errno
-#endif
-
-#define UA_getnameinfo getnameinfo
-#define UA_send(sockfd, buf, len, flags) send(sockfd, buf, (int)(len), flags)
-#define UA_recv(sockfd, buf, len, flags) recv(sockfd, buf, (int)(len), flags)
-#define UA_sendto(sockfd, buf, len, flags, dest_addr, addrlen) sendto(sockfd, (const char*)(buf), (int)(len), flags, dest_addr, (int) (addrlen))
-#define UA_recvfrom(sockfd, buf, len, flags, src_addr, addrlen) recvfrom(sockfd, (char*)(buf), (int)(len), flags, src_addr, addrlen)
-#define UA_htonl htonl
-#define UA_ntohl ntohl
-#define UA_close closesocket
-#define UA_select(nfds, readfds, writefds, exceptfds, timeout) select((int)(nfds), readfds, writefds, exceptfds, timeout)
-#define UA_shutdown shutdown
-#define UA_socket socket
-#define UA_bind bind
-#define UA_listen listen
-#define UA_accept accept
-#define UA_connect(sockfd, addr, addrlen) connect(sockfd, addr, (int)(addrlen))
-#define UA_getaddrinfo getaddrinfo
-#define UA_getsockopt getsockopt
-#define UA_setsockopt(sockfd, level, optname, optval, optlen) setsockopt(sockfd, level, optname, (const char*) (optval), optlen)
-#define UA_freeaddrinfo freeaddrinfo
-#define UA_gethostname gethostname
-#define UA_getsockname getsockname
-#define UA_inet_pton InetPton
-
-#if UA_IPV6
-# include <iphlpapi.h>
-# define UA_if_nametoindex if_nametoindex
-#endif
-
-#ifdef maxStringLength //defined in mingw64
-# undef maxStringLength
-#endif
-
-#ifndef UA_free
-#define UA_free free
-#endif
-#ifndef UA_malloc
-#define UA_malloc malloc
-#endif
-#ifndef UA_calloc
-#define UA_calloc calloc
-#endif
-#ifndef UA_realloc
-#define UA_realloc realloc
-#endif
-
-/* 3rd Argument is the string */
-#define UA_snprintf(source, size, ...) _snprintf_s(source, size, _TRUNCATE, __VA_ARGS__)
-
-#define UA_LOG_SOCKET_ERRNO_WRAP(LOG) { \
- char *errno_str = NULL; \
- FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, \
- NULL, WSAGetLastError(), \
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), \
- (LPSTR)&errno_str, 0, NULL); \
- LOG; \
- LocalFree(errno_str); \
-}
-#define UA_LOG_SOCKET_ERRNO_GAI_WRAP UA_LOG_SOCKET_ERRNO_WRAP
-
-#if UA_MULTITHREADING >= 100
-#define UA_LOCK_TYPE(mutexName) CRITICAL_SECTION mutexName; \
- int mutexName##Counter;
-#define UA_LOCK_INIT(mutexName) InitializeCriticalSection(&mutexName); \
- mutexName##Counter = 0;;
-#define UA_LOCK_DESTROY(mutexName) DeleteCriticalSection(&mutexName);
-#define UA_LOCK(mutexName) EnterCriticalSection(&mutexName); \
- UA_assert(++(mutexName##Counter) == 1);
-#define UA_UNLOCK(mutexName) UA_assert(--(mutexName##Counter) == 0); \
- LeaveCriticalSection(&mutexName);
-#define UA_LOCK_ASSERT(mutexName, num) UA_assert(mutexName##Counter == num);
-#else
-#define UA_LOCK_TYPE(mutexName)
-#define UA_LOCK_TYPE_POINTER(mutexName)
-#define UA_LOCK_INIT(mutexName)
-#define UA_LOCK_DESTROY(mutexName)
-#define UA_LOCK(mutexName)
-#define UA_UNLOCK(mutexName)
-#define UA_LOCK_ASSERT(mutexName, num)
-#endif
-
-
-/* Fix redefinition of SLIST_ENTRY on mingw winnt.h */
-#if !defined(_SYS_QUEUE_H_) && defined(SLIST_ENTRY)
-# undef SLIST_ENTRY
-#endif
-
-#endif /* PLUGINS_ARCH_WIN32_UA_ARCHITECTURE_H_ */
-
-#endif /* UA_ARCHITECTURE_WIN32 */
-
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/arch/posix/ua_architecture.h" ***********************************/
-
-/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
- * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
- *
- * Copyright 2016-2017 (c) Julius Pfrommer, Fraunhofer IOSB
- * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
- */
-
+/**
+ * POSIX Feature Flags
+ * -------------------
+ * These feature flags have to be set before including the first POSIX
+ * header. */
#ifdef UA_ARCHITECTURE_POSIX
-
-
-
-/* Enable POSIX features */
-#if !defined(_XOPEN_SOURCE)
-# define _XOPEN_SOURCE 600
-#endif
-#ifndef _DEFAULT_SOURCE
-# define _DEFAULT_SOURCE
-#endif
+# if !defined(_XOPEN_SOURCE)
+# define _XOPEN_SOURCE 600
+# endif
+# ifndef _DEFAULT_SOURCE
+# define _DEFAULT_SOURCE
+# endif
/* On older systems we need to define _BSD_SOURCE.
* _DEFAULT_SOURCE is an alias for that. */
-#ifndef _BSD_SOURCE
-# define _BSD_SOURCE
-#endif
-
-#include <errno.h>
-#include <arpa/inet.h>
-#include <netinet/in.h>
-#include <netdb.h>
-#include <sys/ioctl.h>
-#include <sys/select.h>
-#include <sys/types.h>
-#include <net/if.h>
-#ifndef UA_sleep_ms
-# include <unistd.h>
-# define UA_sleep_ms(X) usleep(X * 1000)
-#endif
-
-#define OPTVAL_TYPE int
-
-#include <fcntl.h>
-#include <unistd.h> // read, write, close
-
-#ifdef __QNX__
-# include <sys/socket.h>
-#endif
-#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
-# include <sys/param.h>
-# if defined(BSD)
-# include<sys/socket.h>
+# ifndef _BSD_SOURCE
+# define _BSD_SOURCE
# endif
#endif
-#if !defined(__CYGWIN__)
-# include <netinet/tcp.h>
-#endif
-
-/* unsigned int for windows and workaround to a glibc bug */
-/* Additionally if GNU_LIBRARY is not defined, it may be using
- * musl libc (e.g. Docker Alpine) */
-#if defined(__OpenBSD__) || \
- (defined(__GNU_LIBRARY__) && (__GNU_LIBRARY__ <= 6) && \
- (__GLIBC__ <= 2) && (__GLIBC_MINOR__ < 16) || \
- !defined(__GNU_LIBRARY__))
-# define UA_fd_set(fd, fds) FD_SET((unsigned int)fd, fds)
-# define UA_fd_isset(fd, fds) FD_ISSET((unsigned int)fd, fds)
-#else
-# define UA_fd_set(fd, fds) FD_SET(fd, fds)
-# define UA_fd_isset(fd, fds) FD_ISSET(fd, fds)
-#endif
-
-#define UA_access access
-
-#define UA_IPV6 1
-#define UA_SOCKET int
-#define UA_INVALID_SOCKET -1
-#define UA_ERRNO errno
-#define UA_INTERRUPTED EINTR
-#define UA_AGAIN EAGAIN
-#define UA_EAGAIN EAGAIN
-#define UA_WOULDBLOCK EWOULDBLOCK
-#define UA_ERR_CONNECTION_PROGRESS EINPROGRESS
-
-#define UA_ENABLE_LOG_COLORS
-
-#define UA_getnameinfo getnameinfo
-#define UA_send send
-#define UA_recv recv
-#define UA_sendto sendto
-#define UA_recvfrom recvfrom
-#define UA_htonl htonl
-#define UA_ntohl ntohl
-#define UA_close close
-#define UA_select select
-#define UA_shutdown shutdown
-#define UA_socket socket
-#define UA_bind bind
-#define UA_listen listen
-#define UA_accept accept
-#define UA_connect connect
-#define UA_getaddrinfo getaddrinfo
-#define UA_getsockopt getsockopt
-#define UA_setsockopt setsockopt
-#define UA_freeaddrinfo freeaddrinfo
-#define UA_gethostname gethostname
-#define UA_getsockname getsockname
-#define UA_inet_pton inet_pton
-#if UA_IPV6
-# define UA_if_nametoindex if_nametoindex
-#endif
-
-#ifdef UA_ENABLE_MALLOC_SINGLETON
-extern void * (*UA_globalMalloc)(size_t size);
-extern void (*UA_globalFree)(void *ptr);
-extern void * (*UA_globalCalloc)(size_t nelem, size_t elsize);
-extern void * (*UA_globalRealloc)(void *ptr, size_t size);
-# define UA_free(ptr) UA_globalFree(ptr)
-# define UA_malloc(size) UA_globalMalloc(size)
-# define UA_calloc(num, size) UA_globalCalloc(num, size)
-# define UA_realloc(ptr, size) UA_globalRealloc(ptr, size)
-#endif
-
-#include <stdlib.h>
-#ifndef UA_free
-# define UA_free free
-#endif
-#ifndef UA_malloc
-# define UA_malloc malloc
-#endif
-#ifndef UA_calloc
-# define UA_calloc calloc
-#endif
-#ifndef UA_realloc
-# define UA_realloc realloc
-#endif
-
-#include <stdio.h>
-#define UA_snprintf snprintf
-
-#define UA_LOG_SOCKET_ERRNO_WRAP(LOG) { \
- char *errno_str = strerror(errno); \
- LOG; \
-}
-#define UA_LOG_SOCKET_ERRNO_GAI_WRAP(LOG) { \
- const char *errno_str = gai_strerror(errno); \
- LOG; \
-}
-
-#if UA_MULTITHREADING >= 100
-#include <pthread.h>
-#define Sleep(x) sleep(x / 1000)
-#define UA_LOCK_TYPE(mutexName) pthread_mutex_t mutexName; \
- pthread_mutexattr_t mutexName##_attr; \
- int mutexName##Counter;
-#define UA_LOCK_INIT(mutexName) pthread_mutexattr_init(&mutexName##_attr); \
- pthread_mutexattr_settype(&mutexName##_attr, PTHREAD_MUTEX_RECURSIVE); \
- pthread_mutex_init(&mutexName, &mutexName##_attr); \
- mutexName##Counter = 0;
-#define UA_LOCK_DESTROY(mutexName) pthread_mutex_destroy(&mutexName); \
- pthread_mutexattr_destroy(&mutexName##_attr);
-
-#define UA_LOCK(mutexName) pthread_mutex_lock(&mutexName); \
- UA_assert(++(mutexName##Counter) == 1); \
-
-#define UA_UNLOCK(mutexName) UA_assert(--(mutexName##Counter) == 0); \
- pthread_mutex_unlock(&mutexName);
-#define UA_LOCK_ASSERT(mutexName, num) UA_assert(mutexName##Counter == num);
-#else
-#define UA_LOCK_TYPE(mutexName)
-#define UA_LOCK_INIT(mutexName)
-#define UA_LOCK_DESTROY(mutexName)
-#define UA_LOCK(mutexName)
-#define UA_UNLOCK(mutexName)
-#define UA_LOCK_ASSERT(mutexName, num)
-#endif
-
-
-#if defined(__APPLE__) && defined(_SYS_QUEUE_H_)
-// in some compilers there's already a _SYS_QUEUE_H_ which is included first and doesn't have all functions
-
-#undef SLIST_HEAD
-#undef SLIST_HEAD_INITIALIZER
-#undef SLIST_ENTRY
-#undef SLIST_FIRST
-#undef SLIST_END
-#undef SLIST_EMPTY
-#undef SLIST_NEXT
-#undef SLIST_FOREACH
-#undef SLIST_FOREACH_SAFE
-#undef SLIST_INIT
-#undef SLIST_INSERT_AFTER
-#undef SLIST_INSERT_HEAD
-#undef SLIST_REMOVE_AFTER
-#undef SLIST_REMOVE_HEAD
-#undef SLIST_REMOVE
-#undef LIST_HEAD
-#undef LIST_HEAD_INITIALIZER
-#undef LIST_ENTRY
-#undef LIST_FIRST
-#undef LIST_END
-#undef LIST_EMPTY
-#undef LIST_NEXT
-#undef LIST_FOREACH
-#undef LIST_FOREACH_SAFE
-#undef LIST_INIT
-#undef LIST_INSERT_AFTER
-#undef LIST_INSERT_BEFORE
-#undef LIST_INSERT_HEAD
-#undef LIST_REMOVE
-#undef LIST_REPLACE
-#undef SIMPLEQ_HEAD
-#undef SIMPLEQ_HEAD_INITIALIZER
-#undef SIMPLEQ_ENTRY
-#undef SIMPLEQ_FIRST
-#undef SIMPLEQ_END
-#undef SIMPLEQ_EMPTY
-#undef SIMPLEQ_NEXT
-#undef SIMPLEQ_FOREACH
-#undef SIMPLEQ_FOREACH_SAFE
-#undef SIMPLEQ_INIT
-#undef SIMPLEQ_INSERT_HEAD
-#undef SIMPLEQ_INSERT_TAIL
-#undef SIMPLEQ_INSERT_AFTER
-#undef SIMPLEQ_REMOVE_HEAD
-#undef SIMPLEQ_REMOVE_AFTER
-#undef XSIMPLEQ_HEAD
-#undef XSIMPLEQ_ENTRY
-#undef XSIMPLEQ_XOR
-#undef XSIMPLEQ_FIRST
-#undef XSIMPLEQ_END
-#undef XSIMPLEQ_EMPTY
-#undef XSIMPLEQ_NEXT
-#undef XSIMPLEQ_FOREACH
-#undef XSIMPLEQ_FOREACH_SAFE
-#undef XSIMPLEQ_INIT
-#undef XSIMPLEQ_INSERT_HEAD
-#undef XSIMPLEQ_INSERT_TAIL
-#undef XSIMPLEQ_INSERT_AFTER
-#undef XSIMPLEQ_REMOVE_HEAD
-#undef XSIMPLEQ_REMOVE_AFTER
-#undef TAILQ_HEAD
-#undef TAILQ_HEAD_INITIALIZER
-#undef TAILQ_ENTRY
-#undef TAILQ_FIRST
-#undef TAILQ_END
-#undef TAILQ_NEXT
-#undef TAILQ_LAST
-#undef TAILQ_PREV
-#undef TAILQ_EMPTY
-#undef TAILQ_FOREACH
-#undef TAILQ_FOREACH_SAFE
-#undef TAILQ_FOREACH_REVERSE
-#undef TAILQ_FOREACH_REVERSE_SAFE
-#undef TAILQ_INIT
-#undef TAILQ_INSERT_HEAD
-#undef TAILQ_INSERT_TAIL
-#undef TAILQ_INSERT_AFTER
-#undef TAILQ_INSERT_BEFORE
-#undef TAILQ_REMOVE
-#undef TAILQ_REPLACE
-#undef CIRCLEQ_HEAD
-#undef CIRCLEQ_HEAD_INITIALIZER
-#undef CIRCLEQ_ENTRY
-#undef CIRCLEQ_FIRST
-#undef CIRCLEQ_LAST
-#undef CIRCLEQ_END
-#undef CIRCLEQ_NEXT
-#undef CIRCLEQ_PREV
-#undef CIRCLEQ_EMPTY
-#undef CIRCLEQ_FOREACH
-#undef CIRCLEQ_FOREACH_SAFE
-#undef CIRCLEQ_FOREACH_REVERSE
-#undef CIRCLEQ_FOREACH_REVERSE_SAFE
-#undef CIRCLEQ_INIT
-#undef CIRCLEQ_INSERT_AFTER
-#undef CIRCLEQ_INSERT_BEFORE
-#undef CIRCLEQ_INSERT_HEAD
-#undef CIRCLEQ_INSERT_TAIL
-#undef CIRCLEQ_REMOVE
-#undef CIRCLEQ_REPLACE
-
-#undef _SYS_QUEUE_H_
-
-#endif /* defined(__APPLE__) && defined(_SYS_QUEUE_H_) */
+// specific architectures can undef this
+#define UA_HAS_GETIFADDR
-#endif /* UA_ARCHITECTURE_POSIX */
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/deps/ms_stdint.h" ***********************************/
+/**** amalgamated original file "/deps/ms_stdint.h" ****/
// ISO C9x compliant stdint.h for Microsoft Visual Studio
// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
@@ -896,7 +417,7 @@ typedef uint64_t uintmax_t;
#endif // !defined(_MSC_VER) || _MSC_VER >= 1600 ]
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/include/open62541/architecture_definitions.h" ***********************************/
+/**** amalgamated original file "/include/open62541/architecture_definitions.h" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -937,33 +458,92 @@ typedef uint64_t uintmax_t;
# define __PRI_8_LENGTH_MODIFIER__ "hh"
# define __PRI_64_LENGTH_MODIFIER__ "ll"
-# define PRId8 __PRI_8_LENGTH_MODIFIER__ "d"
-# define PRIi8 __PRI_8_LENGTH_MODIFIER__ "i"
-# define PRIo8 __PRI_8_LENGTH_MODIFIER__ "o"
-# define PRIu8 __PRI_8_LENGTH_MODIFIER__ "u"
-# define PRIx8 __PRI_8_LENGTH_MODIFIER__ "x"
-# define PRIX8 __PRI_8_LENGTH_MODIFIER__ "X"
-
-# define PRId16 "hd"
-# define PRIi16 "hi"
-# define PRIo16 "ho"
-# define PRIu16 "hu"
-# define PRIx16 "hx"
-# define PRIX16 "hX"
-
-# define PRId32 "ld"
-# define PRIi32 "li"
-# define PRIo32 "lo"
-# define PRIu32 "lu"
-# define PRIx32 "lx"
-# define PRIX32 "lX"
-
-# define PRId64 __PRI_64_LENGTH_MODIFIER__ "d"
-# define PRIi64 __PRI_64_LENGTH_MODIFIER__ "i"
-# define PRIo64 __PRI_64_LENGTH_MODIFIER__ "o"
-# define PRIu64 __PRI_64_LENGTH_MODIFIER__ "u"
-# define PRIx64 __PRI_64_LENGTH_MODIFIER__ "x"
-# define PRIX64 __PRI_64_LENGTH_MODIFIER__ "X"
+# define PRId8 __PRI_8_LENGTH_MODIFIER__ "d"
+# define PRIi8 __PRI_8_LENGTH_MODIFIER__ "i"
+# define PRIo8 __PRI_8_LENGTH_MODIFIER__ "o"
+# define PRIu8 __PRI_8_LENGTH_MODIFIER__ "u"
+# define PRIx8 __PRI_8_LENGTH_MODIFIER__ "x"
+# define PRIX8 __PRI_8_LENGTH_MODIFIER__ "X"
+
+# define PRId16 "hd"
+# define PRIi16 "hi"
+# define PRIo16 "ho"
+# define PRIu16 "hu"
+# define PRIx16 "hx"
+# define PRIX16 "hX"
+
+# define PRId32 "ld"
+# define PRIi32 "li"
+# define PRIo32 "lo"
+# define PRIu32 "lu"
+# define PRIx32 "lx"
+# define PRIX32 "lX"
+
+# define PRId64 __PRI_64_LENGTH_MODIFIER__ "d"
+# define PRIi64 __PRI_64_LENGTH_MODIFIER__ "i"
+# define PRIo64 __PRI_64_LENGTH_MODIFIER__ "o"
+# define PRIu64 __PRI_64_LENGTH_MODIFIER__ "u"
+# define PRIx64 __PRI_64_LENGTH_MODIFIER__ "x"
+# define PRIX64 __PRI_64_LENGTH_MODIFIER__ "X"
+#endif
+
+/**
+ * Thread-local variables
+ * ---------------------- */
+#if UA_MULTITHREADING >= 100
+# if defined(__GNUC__) /* Also covers clang */
+# define UA_THREAD_LOCAL __thread
+# elif defined(_MSC_VER)
+# define UA_THREAD_LOCAL __declspec(thread)
+# endif
+#endif
+#ifndef UA_THREAD_LOCAL
+# define UA_THREAD_LOCAL
+#endif
+
+/**
+ * Memory Management
+ * -----------------
+ *
+ * The flag ``UA_ENABLE_MALLOC_SINGLETON`` enables singleton (global) variables
+ * with method pointers for memory management (malloc et al.). The method
+ * pointers can be switched out at runtime. Use-cases for this are testing of
+ * constrained memory conditions and arena-based custom memory management.
+ *
+ * If the flag is undefined, then ``UA_malloc`` etc. are set to the default
+ * malloc, as defined in ``/arch/<architecture>/ua_architecture.h``.
+ */
+
+#ifdef UA_ENABLE_MALLOC_SINGLETON
+extern UA_THREAD_LOCAL void * (*UA_mallocSingleton)(size_t size);
+extern UA_THREAD_LOCAL void (*UA_freeSingleton)(void *ptr);
+extern UA_THREAD_LOCAL void * (*UA_callocSingleton)(size_t nelem, size_t elsize);
+extern UA_THREAD_LOCAL void * (*UA_reallocSingleton)(void *ptr, size_t size);
+# define UA_malloc(size) UA_mallocSingleton(size)
+# define UA_free(ptr) UA_freeSingleton(ptr)
+# define UA_calloc(num, size) UA_callocSingleton(num, size)
+# define UA_realloc(ptr, size) UA_reallocSingleton(ptr, size)
+#endif
+
+/* Stack-allocation of memory. Use C99 variable-length arrays if possible.
+ * Otherwise revert to alloca. Note that alloca is not supported on some
+ * plattforms. */
+#ifndef UA_STACKARRAY
+# if defined(__GNUC__) || defined(__clang__)
+# define UA_STACKARRAY(TYPE, NAME, SIZE) TYPE NAME[SIZE]
+# else
+# if defined(__GNUC__) || defined(__clang__)
+# define UA_alloca(size) __builtin_alloca (size)
+# elif defined(_WIN32)
+# define UA_alloca(SIZE) _alloca(SIZE)
+# else
+# include <alloca.h>
+# define UA_alloca(SIZE) alloca(SIZE)
+# endif
+# define UA_STACKARRAY(TYPE, NAME, SIZE) \
+ /* cppcheck-suppress allocaCalled */ \
+ TYPE *(NAME) = (TYPE*)UA_alloca(sizeof(TYPE) * (SIZE))
+# endif
#endif
/**
@@ -1001,6 +581,10 @@ typedef uint64_t uintmax_t;
# define UA_STATIC_ASSERT(cond,msg) typedef char static_assertion_##msg[(cond)?1:-1]
#endif
+/**
+ * Dynamic Linking
+ * ---------------
+ * Explicit attribute for functions to be exported in a shared library. */
#if defined(_WIN32) && defined(UA_DYNAMIC_LINKING)
# ifdef UA_DYNAMIC_LINKING_EXPORT /* export dll */
# ifdef __GNUC__
@@ -1024,6 +608,13 @@ typedef uint64_t uintmax_t;
# define UA_EXPORT /* fallback to default */
#endif
+/**
+ * Threadsafe functions
+ * --------------------
+ * Functions that can be called from independent threads are marked with
+ * the UA_THREADSAFE macro. This is currently only an information for the
+ * developer. It can be used in the future for instrumentation and static
+ * code analysis. */
#define UA_THREADSAFE
/**
@@ -1042,11 +633,25 @@ typedef uint64_t uintmax_t;
# define UA_RESTRICT __restrict
#elif defined(__GNUC__)
# define UA_RESTRICT __restrict__
+#elif defined(__CODEGEARC__)
+# define UA_RESTRICT _RESTRICT
#else
# define UA_RESTRICT restrict
#endif
/**
+ * Likely/Unlikely Conditions
+ * --------------------------
+ * Condition is likely/unlikely, to help branch prediction. */
+#if defined(__GNUC__) || defined(__clang__)
+# define UA_LIKELY(x) __builtin_expect((x), 1)
+# define UA_UNLIKELY(x) __builtin_expect((x), 0)
+#else
+# define UA_LIKELY(x) x
+# define UA_UNLIKELY(x) x
+#endif
+
+/**
* Function attributes
* ------------------- */
#if defined(__GNUC__) || defined(__clang__)
@@ -1055,6 +660,13 @@ typedef uint64_t uintmax_t;
# define UA_FUNC_ATTR_CONST __attribute__((const))
# define UA_FUNC_ATTR_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
# define UA_FORMAT(X,Y) __attribute__ ((format (printf, X, Y)))
+#elif defined(_MSC_VER) && _MSC_VER >= 1800
+# include <sal.h>
+# define UA_FUNC_ATTR_MALLOC
+# define UA_FUNC_ATTR_PURE
+# define UA_FUNC_ATTR_CONST
+# define UA_FUNC_ATTR_WARN_UNUSED_RESULT _Check_return_
+# define UA_FORMAT(X,Y)
#else
# define UA_FUNC_ATTR_MALLOC
# define UA_FUNC_ATTR_PURE
@@ -1079,13 +691,15 @@ typedef uint64_t uintmax_t;
* warnings are only triggered for internal code. */
#if defined(UA_INTERNAL) && (defined(__GNUC__) || defined(__clang__))
-# define UA_INTERNAL_DEPRECATED _Pragma ("GCC warning \"Macro is deprecated for internal use\"")
+# define UA_INTERNAL_DEPRECATED \
+ _Pragma ("GCC warning \"Macro is deprecated for internal use\"")
#else
# define UA_INTERNAL_DEPRECATED
#endif
#if defined(UA_INTERNAL) && (defined(__GNUC__) || defined(__clang__))
-# define UA_INTERNAL_FUNC_ATTR_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
+# define UA_INTERNAL_FUNC_ATTR_WARN_UNUSED_RESULT \
+ __attribute__((warn_unused_result))
#else
# define UA_INTERNAL_FUNC_ATTR_WARN_UNUSED_RESULT
#endif
@@ -1202,13 +816,12 @@ UA_STATIC_ASSERT(sizeof(bool) == 1, cannot_overlay_integers_with_large_bool);
# define UA_BINARY_OVERLAYABLE_FLOAT 0
#endif
-
/* Atomic Operations
* -----------------
* Atomic operations that synchronize across processor cores (for
* multithreading). Only the inline-functions defined next are used. Replace
* with architecture-specific operations if necessary. */
-#if UA_MULTITHREADING >= 200
+#if UA_MULTITHREADING >= 100
#ifdef _MSC_VER /* Visual Studio */
#define UA_atomic_sync() _ReadWriteBarrier()
#else /* GCC/Clang */
@@ -1220,7 +833,7 @@ UA_STATIC_ASSERT(sizeof(bool) == 1, cannot_overlay_integers_with_large_bool);
static UA_INLINE void *
UA_atomic_xchg(void * volatile * addr, void *newptr) {
-#if UA_MULTITHREADING >= 200
+#if UA_MULTITHREADING >= 100
#ifdef _MSC_VER /* Visual Studio */
return _InterlockedExchangePointer(addr, newptr);
#else /* GCC/Clang */
@@ -1235,7 +848,7 @@ UA_atomic_xchg(void * volatile * addr, void *newptr) {
static UA_INLINE void *
UA_atomic_cmpxchg(void * volatile * addr, void *expected, void *newptr) {
-#if UA_MULTITHREADING >= 200
+#if UA_MULTITHREADING >= 100
#ifdef _MSC_VER /* Visual Studio */
return _InterlockedCompareExchangePointer(addr, expected, newptr);
#else /* GCC/Clang */
@@ -1252,7 +865,7 @@ UA_atomic_cmpxchg(void * volatile * addr, void *expected, void *newptr) {
static UA_INLINE uint32_t
UA_atomic_addUInt32(volatile uint32_t *addr, uint32_t increase) {
-#if UA_MULTITHREADING >= 200
+#if UA_MULTITHREADING >= 100
#ifdef _MSC_VER /* Visual Studio */
return _InterlockedExchangeAdd(addr, increase) + increase;
#else /* GCC/Clang */
@@ -1268,7 +881,7 @@ UA_atomic_addUInt32(volatile uint32_t *addr, uint32_t increase) {
static UA_INLINE size_t
UA_atomic_addSize(volatile size_t *addr, size_t increase) {
-#if UA_MULTITHREADING >= 200
+#if UA_MULTITHREADING >= 100
#ifdef _MSC_VER /* Visual Studio */
return _InterlockedExchangeAdd(addr, increase) + increase;
#else /* GCC/Clang */
@@ -1284,7 +897,7 @@ UA_atomic_addSize(volatile size_t *addr, size_t increase) {
static UA_INLINE uint32_t
UA_atomic_subUInt32(volatile uint32_t *addr, uint32_t decrease) {
-#if UA_MULTITHREADING >= 200
+#if UA_MULTITHREADING >= 100
#ifdef _MSC_VER /* Visual Studio */
return _InterlockedExchangeSub(addr, decrease) - decrease;
#else /* GCC/Clang */
@@ -1300,7 +913,7 @@ UA_atomic_subUInt32(volatile uint32_t *addr, uint32_t decrease) {
static UA_INLINE size_t
UA_atomic_subSize(volatile size_t *addr, size_t decrease) {
-#if UA_MULTITHREADING >= 200
+#if UA_MULTITHREADING >= 100
#ifdef _MSC_VER /* Visual Studio */
return _InterlockedExchangeSub(addr, decrease) - decrease;
#else /* GCC/Clang */
@@ -1315,12 +928,534 @@ UA_atomic_subSize(volatile size_t *addr, size_t decrease) {
}
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/build/src_generated/open62541/statuscodes.h" ***********************************/
+/**** amalgamated original file "/arch/win32/ua_architecture.h" ****/
+
+/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
+ * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
+ *
+ * Copyright 2016-2017 (c) Julius Pfrommer, Fraunhofer IOSB
+ * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
+ * Copyright 2021 (c) Christian von Arnim, ISW University of Stuttgart (for VDW and umati)
+ */
+
+#ifdef UA_ARCHITECTURE_WIN32
+
+#ifndef PLUGINS_ARCH_WIN32_UA_ARCHITECTURE_H_
+#define PLUGINS_ARCH_WIN32_UA_ARCHITECTURE_H_
+
+#ifndef _BSD_SOURCE
+# define _BSD_SOURCE
+#endif
+
+/* Disable some security warnings on MSVC */
+#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
+# define _CRT_SECURE_NO_WARNINGS
+#endif
+
+/* Assume that Windows versions are newer than Windows XP */
+#if defined(__MINGW32__) && (!defined(WINVER) || WINVER < 0x501)
+# undef WINVER
+# undef _WIN32_WINDOWS
+# undef _WIN32_WINNT
+# define WINVER 0x0600
+# define _WIN32_WINDOWS 0x0600
+# define _WIN32_WINNT 0x0600 //windows vista version, which included InepPton
+#endif
+
+#include <stdlib.h>
+#if defined(_WIN32) && !defined(__clang__)
+# include <malloc.h>
+#endif
+
+
+#include <stdio.h>
+#include <errno.h>
+#include <winsock2.h>
+#include <windows.h>
+#include <ws2tcpip.h>
+#include <winsock2.h>
+
+#if defined (_MSC_VER) || defined(__clang__)
+# ifndef UNDER_CE
+# include <io.h> //access
+# define UA_access _access
+# endif
+#else
+# include <unistd.h> //access and tests
+# define UA_access access
+#endif
+
+#ifndef _SSIZE_T_DEFINED
+# define ssize_t int
+#endif
+
+#define OPTVAL_TYPE int
+#ifdef UA_sleep_ms
+void UA_sleep_ms(unsigned long ms);
+#else
+# define UA_sleep_ms(X) Sleep(X)
+#endif
+
+// Windows does not support ansi colors
+// #define UA_ENABLE_LOG_COLORS
+
+#define UA_IPV6 1
+
+#if defined(__MINGW32__) && !defined(__clang__) //mingw defines SOCKET as long long unsigned int, giving errors in logging and when comparing with UA_Int32
+# define UA_SOCKET int
+# define UA_INVALID_SOCKET -1
+#else
+# define UA_SOCKET SOCKET
+# define UA_INVALID_SOCKET INVALID_SOCKET
+#endif
+#define UA_ERRNO WSAGetLastError()
+#define UA_INTERRUPTED WSAEINTR
+#define UA_AGAIN WSAEWOULDBLOCK
+#define UA_EAGAIN EAGAIN
+#define UA_WOULDBLOCK WSAEWOULDBLOCK
+#define UA_ERR_CONNECTION_PROGRESS WSAEWOULDBLOCK
+
+#define UA_POLLIN POLLRDNORM
+#define UA_POLLOUT POLLWRNORM
+
+#define UA_fd_set(fd, fds) FD_SET((UA_SOCKET)fd, fds)
+#define UA_fd_isset(fd, fds) FD_ISSET((UA_SOCKET)fd, fds)
+
+#ifdef UNDER_CE
+# define errno
+#endif
+
+#define UA_getnameinfo(sa, salen, host, hostlen, serv, servlen, flags) \
+ getnameinfo(sa, (socklen_t)salen, host, (DWORD)hostlen, serv, (DWORD)servlen, flags)
+#define UA_poll(fds,nfds,timeout) WSAPoll((LPWSAPOLLFD)fds, nfds, timeout)
+#define UA_send(sockfd, buf, len, flags) send(sockfd, buf, (int)(len), flags)
+#define UA_recv(sockfd, buf, len, flags) recv(sockfd, buf, (int)(len), flags)
+#define UA_sendto(sockfd, buf, len, flags, dest_addr, addrlen) sendto(sockfd, (const char*)(buf), (int)(len), flags, dest_addr, (int) (addrlen))
+#define UA_recvfrom(sockfd, buf, len, flags, src_addr, addrlen) recvfrom(sockfd, (char*)(buf), (int)(len), flags, src_addr, addrlen)
+#define UA_recvmsg
+#define UA_htonl htonl
+#define UA_ntohl ntohl
+#define UA_close closesocket
+#define UA_select(nfds, readfds, writefds, exceptfds, timeout) select((int)(nfds), readfds, writefds, exceptfds, timeout)
+#define UA_shutdown shutdown
+#define UA_socket socket
+#define UA_bind bind
+#define UA_listen listen
+#define UA_accept accept
+#define UA_connect(sockfd, addr, addrlen) connect(sockfd, addr, (int)(addrlen))
+#define UA_getaddrinfo getaddrinfo
+#define UA_getsockopt(sockfd, level, optname, optval, optlen) getsockopt(sockfd, level, optname, (char*) (optval), optlen)
+#define UA_setsockopt(sockfd, level, optname, optval, optlen) setsockopt(sockfd, level, optname, (const char*) (optval), optlen)
+#define UA_ioctl
+#define UA_freeaddrinfo freeaddrinfo
+#define UA_gethostname gethostname
+#define UA_getsockname getsockname
+#define UA_inet_pton InetPton
+
+#if UA_IPV6
+# if defined(__WINCRYPT_H__) && defined(UA_ENABLE_ENCRYPTION_LIBRESSL)
+# error "Wincrypt is not compatible with LibreSSL"
+# endif
+# ifdef UA_ENABLE_ENCRYPTION_LIBRESSL
+/* Hack: Prevent Wincrypt-Includes */
+# define __WINCRYPT_H__
+# endif
+
+# include <iphlpapi.h>
+
+# ifdef UA_ENABLE_ENCRYPTION_LIBRESSL
+# undef __WINCRYPT_H__
+# endif
-/*---------------------------------------------------------
- * Autogenerated -- do not modify
- * Generated from /home/pdie/sonstiges/qtopcua/repos/open62541/tools/schema/StatusCode.csv with script /home/pdie/sonstiges/qtopcua/repos/open62541/tools/generate_statuscode_descriptions.py
- *-------------------------------------------------------*/
+# define UA_if_nametoindex if_nametoindex
+#endif
+
+#ifdef maxStringLength //defined in mingw64
+# undef maxStringLength
+#endif
+
+/* Use the standard malloc */
+#ifndef UA_free
+# define UA_free free
+# define UA_malloc malloc
+# define UA_calloc calloc
+# define UA_realloc realloc
+#endif
+
+#ifdef __CODEGEARC__
+#define _snprintf_s(a,b,c,...) snprintf(a,b,__VA_ARGS__)
+#endif
+
+/* 3rd Argument is the string */
+#define UA_snprintf(source, size, ...) _snprintf_s(source, size, _TRUNCATE, __VA_ARGS__)
+#define UA_strncasecmp _strnicmp
+
+#define UA_LOG_SOCKET_ERRNO_WRAP(LOG) { \
+ char *errno_str = NULL; \
+ FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, \
+ NULL, WSAGetLastError(), \
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), \
+ (LPSTR)&errno_str, 0, NULL); \
+ LOG; \
+ LocalFree(errno_str); \
+}
+#define UA_LOG_SOCKET_ERRNO_GAI_WRAP UA_LOG_SOCKET_ERRNO_WRAP
+
+#if UA_MULTITHREADING >= 100
+
+typedef struct {
+ CRITICAL_SECTION mutex;
+ int mutexCounter;
+} UA_Lock;
+
+static UA_INLINE void
+UA_LOCK_INIT(UA_Lock *lock) {
+ InitializeCriticalSection(&lock->mutex);
+ lock->mutexCounter = 0;
+}
+
+static UA_INLINE void
+UA_LOCK_DESTROY(UA_Lock *lock) {
+ DeleteCriticalSection(&lock->mutex);
+}
+
+static UA_INLINE void
+UA_LOCK(UA_Lock *lock) {
+ EnterCriticalSection(&lock->mutex);
+ UA_assert(++(lock->mutexCounter) == 1);
+}
+
+static UA_INLINE void
+UA_UNLOCK(UA_Lock *lock) {
+ UA_assert(--(lock->mutexCounter) == 0);
+ LeaveCriticalSection(&lock->mutex);
+}
+
+static UA_INLINE void
+UA_LOCK_ASSERT(UA_Lock *lock, int num) {
+ UA_assert(lock->mutexCounter == num);
+}
+#else
+#define UA_LOCK_INIT(lock)
+#define UA_LOCK_DESTROY(lock)
+#define UA_LOCK(lock)
+#define UA_UNLOCK(lock)
+#define UA_LOCK_ASSERT(lock, num)
+#endif
+
+
+/* Fix redefinition of SLIST_ENTRY on mingw winnt.h */
+#if !defined(_SYS_QUEUE_H_) && defined(SLIST_ENTRY)
+# undef SLIST_ENTRY
+#endif
+
+#endif /* PLUGINS_ARCH_WIN32_UA_ARCHITECTURE_H_ */
+
+#endif /* UA_ARCHITECTURE_WIN32 */
+
+/**** amalgamated original file "/arch/posix/ua_architecture.h" ****/
+
+/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
+ * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
+ *
+ * Copyright 2016-2017 (c) Julius Pfrommer, Fraunhofer IOSB
+ * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
+ */
+
+#ifdef UA_ARCHITECTURE_POSIX
+
+
+
+#include <errno.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <sys/ioctl.h>
+#include <sys/select.h>
+#include <sys/types.h>
+#include <net/if.h>
+#include <poll.h>
+#ifdef UA_sleep_ms
+void UA_sleep_ms(unsigned long ms);
+#else
+# include <unistd.h>
+# define UA_sleep_ms(X) usleep(X * 1000)
+#endif
+
+#define OPTVAL_TYPE int
+
+#include <fcntl.h>
+#include <unistd.h> // read, write, close
+
+#ifdef __QNX__
+# include <sys/socket.h>
+#endif
+#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
+# include <sys/param.h>
+# if defined(BSD)
+# include<sys/socket.h>
+# endif
+#endif
+
+#include <netinet/tcp.h>
+
+/* unsigned int for windows and workaround to a glibc bug */
+/* Additionally if GNU_LIBRARY is not defined, it may be using
+ * musl libc (e.g. Docker Alpine) */
+#if defined(__OpenBSD__) || \
+ (defined(__GNU_LIBRARY__) && (__GNU_LIBRARY__ <= 6) && \
+ (__GLIBC__ <= 2) && (__GLIBC_MINOR__ < 16) || \
+ !defined(__GNU_LIBRARY__))
+# define UA_fd_set(fd, fds) FD_SET((unsigned int)fd, fds)
+# define UA_fd_isset(fd, fds) FD_ISSET((unsigned int)fd, fds)
+#else
+# define UA_fd_set(fd, fds) FD_SET(fd, fds)
+# define UA_fd_isset(fd, fds) FD_ISSET(fd, fds)
+#endif
+
+#define UA_access access
+
+#define UA_IPV6 1
+#define UA_SOCKET int
+#define UA_INVALID_SOCKET -1
+#define UA_ERRNO errno
+#define UA_INTERRUPTED EINTR
+#define UA_AGAIN EAGAIN
+#define UA_EAGAIN EAGAIN
+#define UA_WOULDBLOCK EWOULDBLOCK
+#define UA_ERR_CONNECTION_PROGRESS EINPROGRESS
+
+#define UA_POLLIN POLLIN
+#define UA_POLLOUT POLLOUT
+
+#define UA_ENABLE_LOG_COLORS
+
+#define UA_poll poll
+#define UA_getnameinfo(sa, salen, host, hostlen, serv, servlen, flags) \
+ getnameinfo(sa, salen, host, hostlen, serv, servlen, flags)
+#define UA_send send
+#define UA_recv recv
+#define UA_sendto sendto
+#define UA_recvfrom recvfrom
+#define UA_recvmsg recvmsg
+#define UA_htonl htonl
+#define UA_ntohl ntohl
+#define UA_close close
+#define UA_select select
+#define UA_shutdown shutdown
+#define UA_socket socket
+#define UA_bind bind
+#define UA_listen listen
+#define UA_accept accept
+#define UA_connect connect
+#define UA_getaddrinfo getaddrinfo
+#define UA_getsockopt getsockopt
+#define UA_setsockopt setsockopt
+#define UA_ioctl ioctl
+#define UA_freeaddrinfo freeaddrinfo
+#define UA_gethostname gethostname
+#define UA_getsockname getsockname
+#define UA_inet_pton inet_pton
+#if UA_IPV6
+# define UA_if_nametoindex if_nametoindex
+#endif
+
+/* Use the standard malloc */
+#include <stdlib.h>
+#ifndef UA_free
+# define UA_free free
+# define UA_malloc malloc
+# define UA_calloc calloc
+# define UA_realloc realloc
+#endif
+
+#include <stdio.h>
+#include <strings.h>
+#define UA_snprintf snprintf
+#define UA_strncasecmp strncasecmp
+
+#define UA_clean_errno(STR_FUN) (errno == 0 ? (char*) "None" : (STR_FUN)(errno))
+
+#define UA_LOG_SOCKET_ERRNO_WRAP(LOG) { \
+ char *errno_str = UA_clean_errno(strerror); \
+ LOG; \
+ errno = 0; \
+}
+#define UA_LOG_SOCKET_ERRNO_GAI_WRAP(LOG) { \
+ const char *errno_str = UA_clean_errno(gai_strerror); \
+ LOG; \
+ errno = 0; \
+}
+
+#if UA_MULTITHREADING >= 100
+
+#include <pthread.h>
+
+typedef struct {
+ pthread_mutex_t mutex;
+ pthread_mutexattr_t mutexAttr;
+ int mutexCounter;
+} UA_Lock;
+
+static UA_INLINE void
+UA_LOCK_INIT(UA_Lock *lock) {
+ pthread_mutexattr_init(&lock->mutexAttr);
+ pthread_mutexattr_settype(&lock->mutexAttr, PTHREAD_MUTEX_RECURSIVE);
+ pthread_mutex_init(&lock->mutex, &lock->mutexAttr);
+ lock->mutexCounter = 0;
+}
+
+static UA_INLINE void
+UA_LOCK_DESTROY(UA_Lock *lock) {
+ pthread_mutex_destroy(&lock->mutex);
+ pthread_mutexattr_destroy(&lock->mutexAttr);
+}
+
+static UA_INLINE void
+UA_LOCK(UA_Lock *lock) {
+ pthread_mutex_lock(&lock->mutex);
+ UA_assert(++(lock->mutexCounter) == 1);
+}
+
+static UA_INLINE void
+UA_UNLOCK(UA_Lock *lock) {
+ UA_assert(--(lock->mutexCounter) == 0);
+ pthread_mutex_unlock(&lock->mutex);
+}
+
+static UA_INLINE void
+UA_LOCK_ASSERT(UA_Lock *lock, int num) {
+ UA_assert(lock->mutexCounter == num);
+}
+#else
+#define UA_EMPTY_STATEMENT \
+ do { \
+ } while(0)
+#define UA_LOCK_INIT(lock) UA_EMPTY_STATEMENT
+#define UA_LOCK_DESTROY(lock) UA_EMPTY_STATEMENT
+#define UA_LOCK(lock) UA_EMPTY_STATEMENT
+#define UA_UNLOCK(lock) UA_EMPTY_STATEMENT
+#define UA_LOCK_ASSERT(lock, num) UA_EMPTY_STATEMENT
+#endif
+
+
+#if defined(__APPLE__) && defined(_SYS_QUEUE_H_)
+// in some compilers there's already a _SYS_QUEUE_H_ which is included first and doesn't
+// have all functions
+
+#undef SLIST_HEAD
+#undef SLIST_HEAD_INITIALIZER
+#undef SLIST_ENTRY
+#undef SLIST_FIRST
+#undef SLIST_END
+#undef SLIST_EMPTY
+#undef SLIST_NEXT
+#undef SLIST_FOREACH
+#undef SLIST_FOREACH_SAFE
+#undef SLIST_INIT
+#undef SLIST_INSERT_AFTER
+#undef SLIST_INSERT_HEAD
+#undef SLIST_REMOVE_AFTER
+#undef SLIST_REMOVE_HEAD
+#undef SLIST_REMOVE
+#undef LIST_HEAD
+#undef LIST_HEAD_INITIALIZER
+#undef LIST_ENTRY
+#undef LIST_FIRST
+#undef LIST_END
+#undef LIST_EMPTY
+#undef LIST_NEXT
+#undef LIST_FOREACH
+#undef LIST_FOREACH_SAFE
+#undef LIST_INIT
+#undef LIST_INSERT_AFTER
+#undef LIST_INSERT_BEFORE
+#undef LIST_INSERT_HEAD
+#undef LIST_REMOVE
+#undef LIST_REPLACE
+#undef SIMPLEQ_HEAD
+#undef SIMPLEQ_HEAD_INITIALIZER
+#undef SIMPLEQ_ENTRY
+#undef SIMPLEQ_FIRST
+#undef SIMPLEQ_END
+#undef SIMPLEQ_EMPTY
+#undef SIMPLEQ_NEXT
+#undef SIMPLEQ_FOREACH
+#undef SIMPLEQ_FOREACH_SAFE
+#undef SIMPLEQ_INIT
+#undef SIMPLEQ_INSERT_HEAD
+#undef SIMPLEQ_INSERT_TAIL
+#undef SIMPLEQ_INSERT_AFTER
+#undef SIMPLEQ_REMOVE_HEAD
+#undef SIMPLEQ_REMOVE_AFTER
+#undef XSIMPLEQ_HEAD
+#undef XSIMPLEQ_ENTRY
+#undef XSIMPLEQ_XOR
+#undef XSIMPLEQ_FIRST
+#undef XSIMPLEQ_END
+#undef XSIMPLEQ_EMPTY
+#undef XSIMPLEQ_NEXT
+#undef XSIMPLEQ_FOREACH
+#undef XSIMPLEQ_FOREACH_SAFE
+#undef XSIMPLEQ_INIT
+#undef XSIMPLEQ_INSERT_HEAD
+#undef XSIMPLEQ_INSERT_TAIL
+#undef XSIMPLEQ_INSERT_AFTER
+#undef XSIMPLEQ_REMOVE_HEAD
+#undef XSIMPLEQ_REMOVE_AFTER
+#undef TAILQ_HEAD
+#undef TAILQ_HEAD_INITIALIZER
+#undef TAILQ_ENTRY
+#undef TAILQ_FIRST
+#undef TAILQ_END
+#undef TAILQ_NEXT
+#undef TAILQ_LAST
+#undef TAILQ_PREV
+#undef TAILQ_EMPTY
+#undef TAILQ_FOREACH
+#undef TAILQ_FOREACH_SAFE
+#undef TAILQ_FOREACH_REVERSE
+#undef TAILQ_FOREACH_REVERSE_SAFE
+#undef TAILQ_INIT
+#undef TAILQ_INSERT_HEAD
+#undef TAILQ_INSERT_TAIL
+#undef TAILQ_INSERT_AFTER
+#undef TAILQ_INSERT_BEFORE
+#undef TAILQ_REMOVE
+#undef TAILQ_REPLACE
+#undef CIRCLEQ_HEAD
+#undef CIRCLEQ_HEAD_INITIALIZER
+#undef CIRCLEQ_ENTRY
+#undef CIRCLEQ_FIRST
+#undef CIRCLEQ_LAST
+#undef CIRCLEQ_END
+#undef CIRCLEQ_NEXT
+#undef CIRCLEQ_PREV
+#undef CIRCLEQ_EMPTY
+#undef CIRCLEQ_FOREACH
+#undef CIRCLEQ_FOREACH_SAFE
+#undef CIRCLEQ_FOREACH_REVERSE
+#undef CIRCLEQ_FOREACH_REVERSE_SAFE
+#undef CIRCLEQ_INIT
+#undef CIRCLEQ_INSERT_AFTER
+#undef CIRCLEQ_INSERT_BEFORE
+#undef CIRCLEQ_INSERT_HEAD
+#undef CIRCLEQ_INSERT_TAIL
+#undef CIRCLEQ_REMOVE
+#undef CIRCLEQ_REPLACE
+
+#undef _SYS_QUEUE_H_
+
+#endif /* defined(__APPLE__) && defined(_SYS_QUEUE_H_) */
+
+
+#endif /* UA_ARCHITECTURE_POSIX */
+
+/**** amalgamated original file "/build/src_generated/open62541/statuscodes.h" ****/
+
+/**********************************
+ * Autogenerated -- do not modify *
+ **********************************/
/**
* .. _statuscodes:
@@ -1333,722 +1468,776 @@ UA_atomic_subSize(volatile size_t *addr, size_t decrease) {
* with the OPC UA standard. */
/* These StatusCodes are manually generated. */
-#define UA_STATUSCODE_GOOD 0x00
#define UA_STATUSCODE_INFOTYPE_DATAVALUE 0x00000400
#define UA_STATUSCODE_INFOBITS_OVERFLOW 0x00000080
-/* An unexpected error occurred. */
+/* "The operation succeeded." */
+#define UA_STATUSCODE_GOOD 0x00000000
+
+/* "The operation was uncertain." */
+#define UA_STATUSCODE_UNCERTAIN 0x40000000
+
+/* "The operation failed." */
+#define UA_STATUSCODE_BAD 0x80000000
+
+/* "An unexpected error occurred." */
#define UA_STATUSCODE_BADUNEXPECTEDERROR 0x80010000
-/* An internal error occurred as a result of a programming or configuration error. */
+/* "An internal error occurred as a result of a programming or configuration error." */
#define UA_STATUSCODE_BADINTERNALERROR 0x80020000
-/* Not enough memory to complete the operation. */
+/* "Not enough memory to complete the operation." */
#define UA_STATUSCODE_BADOUTOFMEMORY 0x80030000
-/* An operating system resource is not available. */
+/* "An operating system resource is not available." */
#define UA_STATUSCODE_BADRESOURCEUNAVAILABLE 0x80040000
-/* A low level communication error occurred. */
+/* "A low level communication error occurred." */
#define UA_STATUSCODE_BADCOMMUNICATIONERROR 0x80050000
-/* Encoding halted because of invalid data in the objects being serialized. */
+/* "Encoding halted because of invalid data in the objects being serialized." */
#define UA_STATUSCODE_BADENCODINGERROR 0x80060000
-/* Decoding halted because of invalid data in the stream. */
+/* "Decoding halted because of invalid data in the stream." */
#define UA_STATUSCODE_BADDECODINGERROR 0x80070000
-/* The message encoding/decoding limits imposed by the stack have been exceeded. */
+/* "The message encoding/decoding limits imposed by the stack have been exceeded." */
#define UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED 0x80080000
-/* The request message size exceeds limits set by the server. */
+/* "The request message size exceeds limits set by the server." */
#define UA_STATUSCODE_BADREQUESTTOOLARGE 0x80B80000
-/* The response message size exceeds limits set by the client. */
+/* "The response message size exceeds limits set by the client." */
#define UA_STATUSCODE_BADRESPONSETOOLARGE 0x80B90000
-/* An unrecognized response was received from the server. */
+/* "An unrecognized response was received from the server." */
#define UA_STATUSCODE_BADUNKNOWNRESPONSE 0x80090000
-/* The operation timed out. */
+/* "The operation timed out." */
#define UA_STATUSCODE_BADTIMEOUT 0x800A0000
-/* The server does not support the requested service. */
+/* "The server does not support the requested service." */
#define UA_STATUSCODE_BADSERVICEUNSUPPORTED 0x800B0000
-/* The operation was cancelled because the application is shutting down. */
+/* "The operation was cancelled because the application is shutting down." */
#define UA_STATUSCODE_BADSHUTDOWN 0x800C0000
-/* The operation could not complete because the client is not connected to the server. */
+/* "The operation could not complete because the client is not connected to the server." */
#define UA_STATUSCODE_BADSERVERNOTCONNECTED 0x800D0000
-/* The server has stopped and cannot process any requests. */
+/* "The server has stopped and cannot process any requests." */
#define UA_STATUSCODE_BADSERVERHALTED 0x800E0000
-/* There was nothing to do because the client passed a list of operations with no elements. */
+/* "There was nothing to do because the client passed a list of operations with no elements." */
#define UA_STATUSCODE_BADNOTHINGTODO 0x800F0000
-/* The request could not be processed because it specified too many operations. */
+/* "The request could not be processed because it specified too many operations." */
#define UA_STATUSCODE_BADTOOMANYOPERATIONS 0x80100000
-/* The request could not be processed because there are too many monitored items in the subscription. */
+/* "The request could not be processed because there are too many monitored items in the subscription." */
#define UA_STATUSCODE_BADTOOMANYMONITOREDITEMS 0x80DB0000
-/* The extension object cannot be (de)serialized because the data type id is not recognized. */
+/* "The extension object cannot be (de)serialized because the data type id is not recognized." */
#define UA_STATUSCODE_BADDATATYPEIDUNKNOWN 0x80110000
-/* The certificate provided as a parameter is not valid. */
+/* "The certificate provided as a parameter is not valid." */
#define UA_STATUSCODE_BADCERTIFICATEINVALID 0x80120000
-/* An error occurred verifying security. */
+/* "An error occurred verifying security." */
#define UA_STATUSCODE_BADSECURITYCHECKSFAILED 0x80130000
-/* The certificate does not meet the requirements of the security policy. */
+/* "The certificate does not meet the requirements of the security policy." */
#define UA_STATUSCODE_BADCERTIFICATEPOLICYCHECKFAILED 0x81140000
-/* The certificate has expired or is not yet valid. */
+/* "The certificate has expired or is not yet valid." */
#define UA_STATUSCODE_BADCERTIFICATETIMEINVALID 0x80140000
-/* An issuer certificate has expired or is not yet valid. */
+/* "An issuer certificate has expired or is not yet valid." */
#define UA_STATUSCODE_BADCERTIFICATEISSUERTIMEINVALID 0x80150000
-/* The HostName used to connect to a server does not match a HostName in the certificate. */
+/* "The HostName used to connect to a server does not match a HostName in the certificate." */
#define UA_STATUSCODE_BADCERTIFICATEHOSTNAMEINVALID 0x80160000
-/* The URI specified in the ApplicationDescription does not match the URI in the certificate. */
+/* "The URI specified in the ApplicationDescription does not match the URI in the certificate." */
#define UA_STATUSCODE_BADCERTIFICATEURIINVALID 0x80170000
-/* The certificate may not be used for the requested operation. */
+/* "The certificate may not be used for the requested operation." */
#define UA_STATUSCODE_BADCERTIFICATEUSENOTALLOWED 0x80180000
-/* The issuer certificate may not be used for the requested operation. */
+/* "The issuer certificate may not be used for the requested operation." */
#define UA_STATUSCODE_BADCERTIFICATEISSUERUSENOTALLOWED 0x80190000
-/* The certificate is not trusted. */
+/* "The certificate is not trusted." */
#define UA_STATUSCODE_BADCERTIFICATEUNTRUSTED 0x801A0000
-/* It was not possible to determine if the certificate has been revoked. */
+/* "It was not possible to determine if the certificate has been revoked." */
#define UA_STATUSCODE_BADCERTIFICATEREVOCATIONUNKNOWN 0x801B0000
-/* It was not possible to determine if the issuer certificate has been revoked. */
+/* "It was not possible to determine if the issuer certificate has been revoked." */
#define UA_STATUSCODE_BADCERTIFICATEISSUERREVOCATIONUNKNOWN 0x801C0000
-/* The certificate has been revoked. */
+/* "The certificate has been revoked." */
#define UA_STATUSCODE_BADCERTIFICATEREVOKED 0x801D0000
-/* The issuer certificate has been revoked. */
+/* "The issuer certificate has been revoked." */
#define UA_STATUSCODE_BADCERTIFICATEISSUERREVOKED 0x801E0000
-/* The certificate chain is incomplete. */
+/* "The certificate chain is incomplete." */
#define UA_STATUSCODE_BADCERTIFICATECHAININCOMPLETE 0x810D0000
-/* User does not have permission to perform the requested operation. */
+/* "User does not have permission to perform the requested operation." */
#define UA_STATUSCODE_BADUSERACCESSDENIED 0x801F0000
-/* The user identity token is not valid. */
+/* "The user identity token is not valid." */
#define UA_STATUSCODE_BADIDENTITYTOKENINVALID 0x80200000
-/* The user identity token is valid but the server has rejected it. */
+/* "The user identity token is valid but the server has rejected it." */
#define UA_STATUSCODE_BADIDENTITYTOKENREJECTED 0x80210000
-/* The specified secure channel is no longer valid. */
+/* "The specified secure channel is no longer valid." */
#define UA_STATUSCODE_BADSECURECHANNELIDINVALID 0x80220000
-/* The timestamp is outside the range allowed by the server. */
+/* "The timestamp is outside the range allowed by the server." */
#define UA_STATUSCODE_BADINVALIDTIMESTAMP 0x80230000
-/* The nonce does appear to be not a random value or it is not the correct length. */
+/* "The nonce does appear to be not a random value or it is not the correct length." */
#define UA_STATUSCODE_BADNONCEINVALID 0x80240000
-/* The session id is not valid. */
+/* "The session id is not valid." */
#define UA_STATUSCODE_BADSESSIONIDINVALID 0x80250000
-/* The session was closed by the client. */
+/* "The session was closed by the client." */
#define UA_STATUSCODE_BADSESSIONCLOSED 0x80260000
-/* The session cannot be used because ActivateSession has not been called. */
+/* "The session cannot be used because ActivateSession has not been called." */
#define UA_STATUSCODE_BADSESSIONNOTACTIVATED 0x80270000
-/* The subscription id is not valid. */
+/* "The subscription id is not valid." */
#define UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID 0x80280000
-/* The header for the request is missing or invalid. */
+/* "The header for the request is missing or invalid." */
#define UA_STATUSCODE_BADREQUESTHEADERINVALID 0x802A0000
-/* The timestamps to return parameter is invalid. */
+/* "The timestamps to return parameter is invalid." */
#define UA_STATUSCODE_BADTIMESTAMPSTORETURNINVALID 0x802B0000
-/* The request was cancelled by the client. */
+/* "The request was cancelled by the client." */
#define UA_STATUSCODE_BADREQUESTCANCELLEDBYCLIENT 0x802C0000
-/* Too many arguments were provided. */
+/* "Too many arguments were provided." */
#define UA_STATUSCODE_BADTOOMANYARGUMENTS 0x80E50000
-/* The server requires a license to operate in general or to perform a service or operation */
+/* "The server requires a license to operate in general or to perform a service or operation */
#define UA_STATUSCODE_BADLICENSEEXPIRED 0x810E0000
-/* The server has limits on number of allowed operations / objects */
+/* "The server has limits on number of allowed operations / objects */
#define UA_STATUSCODE_BADLICENSELIMITSEXCEEDED 0x810F0000
-/* The server does not have a license which is required to operate in general or to perform a service or operation. */
+/* "The server does not have a license which is required to operate in general or to perform a service or operation." */
#define UA_STATUSCODE_BADLICENSENOTAVAILABLE 0x81100000
-/* The subscription was transferred to another session. */
+/* "The subscription was transferred to another session." */
#define UA_STATUSCODE_GOODSUBSCRIPTIONTRANSFERRED 0x002D0000
-/* The processing will complete asynchronously. */
+/* "The processing will complete asynchronously." */
#define UA_STATUSCODE_GOODCOMPLETESASYNCHRONOUSLY 0x002E0000
-/* Sampling has slowed down due to resource limitations. */
+/* "Sampling has slowed down due to resource limitations." */
#define UA_STATUSCODE_GOODOVERLOAD 0x002F0000
-/* The value written was accepted but was clamped. */
+/* "The value written was accepted but was clamped." */
#define UA_STATUSCODE_GOODCLAMPED 0x00300000
-/* Communication with the data source is defined */
+/* "Communication with the data source is defined */
#define UA_STATUSCODE_BADNOCOMMUNICATION 0x80310000
-/* Waiting for the server to obtain values from the underlying data source. */
+/* "Waiting for the server to obtain values from the underlying data source." */
#define UA_STATUSCODE_BADWAITINGFORINITIALDATA 0x80320000
-/* The syntax of the node id is not valid. */
+/* "The syntax of the node id is not valid." */
#define UA_STATUSCODE_BADNODEIDINVALID 0x80330000
-/* The node id refers to a node that does not exist in the server address space. */
+/* "The node id refers to a node that does not exist in the server address space." */
#define UA_STATUSCODE_BADNODEIDUNKNOWN 0x80340000
-/* The attribute is not supported for the specified Node. */
+/* "The attribute is not supported for the specified Node." */
#define UA_STATUSCODE_BADATTRIBUTEIDINVALID 0x80350000
-/* The syntax of the index range parameter is invalid. */
+/* "The syntax of the index range parameter is invalid." */
#define UA_STATUSCODE_BADINDEXRANGEINVALID 0x80360000
-/* No data exists within the range of indexes specified. */
+/* "No data exists within the range of indexes specified." */
#define UA_STATUSCODE_BADINDEXRANGENODATA 0x80370000
-/* The data encoding is invalid. */
+/* "The data encoding is invalid." */
#define UA_STATUSCODE_BADDATAENCODINGINVALID 0x80380000
-/* The server does not support the requested data encoding for the node. */
+/* "The server does not support the requested data encoding for the node." */
#define UA_STATUSCODE_BADDATAENCODINGUNSUPPORTED 0x80390000
-/* The access level does not allow reading or subscribing to the Node. */
+/* "The access level does not allow reading or subscribing to the Node." */
#define UA_STATUSCODE_BADNOTREADABLE 0x803A0000
-/* The access level does not allow writing to the Node. */
+/* "The access level does not allow writing to the Node." */
#define UA_STATUSCODE_BADNOTWRITABLE 0x803B0000
-/* The value was out of range. */
+/* "The value was out of range." */
#define UA_STATUSCODE_BADOUTOFRANGE 0x803C0000
-/* The requested operation is not supported. */
+/* "The requested operation is not supported." */
#define UA_STATUSCODE_BADNOTSUPPORTED 0x803D0000
-/* A requested item was not found or a search operation ended without success. */
+/* "A requested item was not found or a search operation ended without success." */
#define UA_STATUSCODE_BADNOTFOUND 0x803E0000
-/* The object cannot be used because it has been deleted. */
+/* "The object cannot be used because it has been deleted." */
#define UA_STATUSCODE_BADOBJECTDELETED 0x803F0000
-/* Requested operation is not implemented. */
+/* "Requested operation is not implemented." */
#define UA_STATUSCODE_BADNOTIMPLEMENTED 0x80400000
-/* The monitoring mode is invalid. */
+/* "The monitoring mode is invalid." */
#define UA_STATUSCODE_BADMONITORINGMODEINVALID 0x80410000
-/* The monitoring item id does not refer to a valid monitored item. */
+/* "The monitoring item id does not refer to a valid monitored item." */
#define UA_STATUSCODE_BADMONITOREDITEMIDINVALID 0x80420000
-/* The monitored item filter parameter is not valid. */
+/* "The monitored item filter parameter is not valid." */
#define UA_STATUSCODE_BADMONITOREDITEMFILTERINVALID 0x80430000
-/* The server does not support the requested monitored item filter. */
+/* "The server does not support the requested monitored item filter." */
#define UA_STATUSCODE_BADMONITOREDITEMFILTERUNSUPPORTED 0x80440000
-/* A monitoring filter cannot be used in combination with the attribute specified. */
+/* "A monitoring filter cannot be used in combination with the attribute specified." */
#define UA_STATUSCODE_BADFILTERNOTALLOWED 0x80450000
-/* A mandatory structured parameter was missing or null. */
+/* "A mandatory structured parameter was missing or null." */
#define UA_STATUSCODE_BADSTRUCTUREMISSING 0x80460000
-/* The event filter is not valid. */
+/* "The event filter is not valid." */
#define UA_STATUSCODE_BADEVENTFILTERINVALID 0x80470000
-/* The content filter is not valid. */
+/* "The content filter is not valid." */
#define UA_STATUSCODE_BADCONTENTFILTERINVALID 0x80480000
-/* An unrecognized operator was provided in a filter. */
+/* "An unrecognized operator was provided in a filter." */
#define UA_STATUSCODE_BADFILTEROPERATORINVALID 0x80C10000
-/* A valid operator was provided */
+/* "A valid operator was provided */
#define UA_STATUSCODE_BADFILTEROPERATORUNSUPPORTED 0x80C20000
-/* The number of operands provided for the filter operator was less then expected for the operand provided. */
+/* "The number of operands provided for the filter operator was less then expected for the operand provided." */
#define UA_STATUSCODE_BADFILTEROPERANDCOUNTMISMATCH 0x80C30000
-/* The operand used in a content filter is not valid. */
+/* "The operand used in a content filter is not valid." */
#define UA_STATUSCODE_BADFILTEROPERANDINVALID 0x80490000
-/* The referenced element is not a valid element in the content filter. */
+/* "The referenced element is not a valid element in the content filter." */
#define UA_STATUSCODE_BADFILTERELEMENTINVALID 0x80C40000
-/* The referenced literal is not a valid value. */
+/* "The referenced literal is not a valid value." */
#define UA_STATUSCODE_BADFILTERLITERALINVALID 0x80C50000
-/* The continuation point provide is longer valid. */
+/* "The continuation point provide is longer valid." */
#define UA_STATUSCODE_BADCONTINUATIONPOINTINVALID 0x804A0000
-/* The operation could not be processed because all continuation points have been allocated. */
+/* "The operation could not be processed because all continuation points have been allocated." */
#define UA_STATUSCODE_BADNOCONTINUATIONPOINTS 0x804B0000
-/* The reference type id does not refer to a valid reference type node. */
+/* "The reference type id does not refer to a valid reference type node." */
#define UA_STATUSCODE_BADREFERENCETYPEIDINVALID 0x804C0000
-/* The browse direction is not valid. */
+/* "The browse direction is not valid." */
#define UA_STATUSCODE_BADBROWSEDIRECTIONINVALID 0x804D0000
-/* The node is not part of the view. */
+/* "The node is not part of the view." */
#define UA_STATUSCODE_BADNODENOTINVIEW 0x804E0000
-/* The number was not accepted because of a numeric overflow. */
+/* "The number was not accepted because of a numeric overflow." */
#define UA_STATUSCODE_BADNUMERICOVERFLOW 0x81120000
-/* The ServerUri is not a valid URI. */
+/* "The ServerUri is not a valid URI." */
#define UA_STATUSCODE_BADSERVERURIINVALID 0x804F0000
-/* No ServerName was specified. */
+/* "No ServerName was specified." */
#define UA_STATUSCODE_BADSERVERNAMEMISSING 0x80500000
-/* No DiscoveryUrl was specified. */
+/* "No DiscoveryUrl was specified." */
#define UA_STATUSCODE_BADDISCOVERYURLMISSING 0x80510000
-/* The semaphore file specified by the client is not valid. */
+/* "The semaphore file specified by the client is not valid." */
#define UA_STATUSCODE_BADSEMPAHOREFILEMISSING 0x80520000
-/* The security token request type is not valid. */
+/* "The security token request type is not valid." */
#define UA_STATUSCODE_BADREQUESTTYPEINVALID 0x80530000
-/* The security mode does not meet the requirements set by the server. */
+/* "The security mode does not meet the requirements set by the server." */
#define UA_STATUSCODE_BADSECURITYMODEREJECTED 0x80540000
-/* The security policy does not meet the requirements set by the server. */
+/* "The security policy does not meet the requirements set by the server." */
#define UA_STATUSCODE_BADSECURITYPOLICYREJECTED 0x80550000
-/* The server has reached its maximum number of sessions. */
+/* "The server has reached its maximum number of sessions." */
#define UA_STATUSCODE_BADTOOMANYSESSIONS 0x80560000
-/* The user token signature is missing or invalid. */
+/* "The user token signature is missing or invalid." */
#define UA_STATUSCODE_BADUSERSIGNATUREINVALID 0x80570000
-/* The signature generated with the client certificate is missing or invalid. */
+/* "The signature generated with the client certificate is missing or invalid." */
#define UA_STATUSCODE_BADAPPLICATIONSIGNATUREINVALID 0x80580000
-/* The client did not provide at least one software certificate that is valid and meets the profile requirements for the server. */
+/* "The client did not provide at least one software certificate that is valid and meets the profile requirements for the server." */
#define UA_STATUSCODE_BADNOVALIDCERTIFICATES 0x80590000
-/* The server does not support changing the user identity assigned to the session. */
+/* "The server does not support changing the user identity assigned to the session." */
#define UA_STATUSCODE_BADIDENTITYCHANGENOTSUPPORTED 0x80C60000
-/* The request was cancelled by the client with the Cancel service. */
+/* "The request was cancelled by the client with the Cancel service." */
#define UA_STATUSCODE_BADREQUESTCANCELLEDBYREQUEST 0x805A0000
-/* The parent node id does not to refer to a valid node. */
+/* "The parent node id does not to refer to a valid node." */
#define UA_STATUSCODE_BADPARENTNODEIDINVALID 0x805B0000
-/* The reference could not be created because it violates constraints imposed by the data model. */
+/* "The reference could not be created because it violates constraints imposed by the data model." */
#define UA_STATUSCODE_BADREFERENCENOTALLOWED 0x805C0000
-/* The requested node id was reject because it was either invalid or server does not allow node ids to be specified by the client. */
+/* "The requested node id was reject because it was either invalid or server does not allow node ids to be specified by the client." */
#define UA_STATUSCODE_BADNODEIDREJECTED 0x805D0000
-/* The requested node id is already used by another node. */
+/* "The requested node id is already used by another node." */
#define UA_STATUSCODE_BADNODEIDEXISTS 0x805E0000
-/* The node class is not valid. */
+/* "The node class is not valid." */
#define UA_STATUSCODE_BADNODECLASSINVALID 0x805F0000
-/* The browse name is invalid. */
+/* "The browse name is invalid." */
#define UA_STATUSCODE_BADBROWSENAMEINVALID 0x80600000
-/* The browse name is not unique among nodes that share the same relationship with the parent. */
+/* "The browse name is not unique among nodes that share the same relationship with the parent." */
#define UA_STATUSCODE_BADBROWSENAMEDUPLICATED 0x80610000
-/* The node attributes are not valid for the node class. */
+/* "The node attributes are not valid for the node class." */
#define UA_STATUSCODE_BADNODEATTRIBUTESINVALID 0x80620000
-/* The type definition node id does not reference an appropriate type node. */
+/* "The type definition node id does not reference an appropriate type node." */
#define UA_STATUSCODE_BADTYPEDEFINITIONINVALID 0x80630000
-/* The source node id does not reference a valid node. */
+/* "The source node id does not reference a valid node." */
#define UA_STATUSCODE_BADSOURCENODEIDINVALID 0x80640000
-/* The target node id does not reference a valid node. */
+/* "The target node id does not reference a valid node." */
#define UA_STATUSCODE_BADTARGETNODEIDINVALID 0x80650000
-/* The reference type between the nodes is already defined. */
+/* "The reference type between the nodes is already defined." */
#define UA_STATUSCODE_BADDUPLICATEREFERENCENOTALLOWED 0x80660000
-/* The server does not allow this type of self reference on this node. */
+/* "The server does not allow this type of self reference on this node." */
#define UA_STATUSCODE_BADINVALIDSELFREFERENCE 0x80670000
-/* The reference type is not valid for a reference to a remote server. */
+/* "The reference type is not valid for a reference to a remote server." */
#define UA_STATUSCODE_BADREFERENCELOCALONLY 0x80680000
-/* The server will not allow the node to be deleted. */
+/* "The server will not allow the node to be deleted." */
#define UA_STATUSCODE_BADNODELETERIGHTS 0x80690000
-/* The server was not able to delete all target references. */
+/* "The server was not able to delete all target references." */
#define UA_STATUSCODE_UNCERTAINREFERENCENOTDELETED 0x40BC0000
-/* The server index is not valid. */
+/* "The server index is not valid." */
#define UA_STATUSCODE_BADSERVERINDEXINVALID 0x806A0000
-/* The view id does not refer to a valid view node. */
+/* "The view id does not refer to a valid view node." */
#define UA_STATUSCODE_BADVIEWIDUNKNOWN 0x806B0000
-/* The view timestamp is not available or not supported. */
+/* "The view timestamp is not available or not supported." */
#define UA_STATUSCODE_BADVIEWTIMESTAMPINVALID 0x80C90000
-/* The view parameters are not consistent with each other. */
+/* "The view parameters are not consistent with each other." */
#define UA_STATUSCODE_BADVIEWPARAMETERMISMATCH 0x80CA0000
-/* The view version is not available or not supported. */
+/* "The view version is not available or not supported." */
#define UA_STATUSCODE_BADVIEWVERSIONINVALID 0x80CB0000
-/* The list of references may not be complete because the underlying system is not available. */
+/* "The list of references may not be complete because the underlying system is not available." */
#define UA_STATUSCODE_UNCERTAINNOTALLNODESAVAILABLE 0x40C00000
-/* The server should have followed a reference to a node in a remote server but did not. The result set may be incomplete. */
+/* "The server should have followed a reference to a node in a remote server but did not. The result set may be incomplete." */
#define UA_STATUSCODE_GOODRESULTSMAYBEINCOMPLETE 0x00BA0000
-/* The provided Nodeid was not a type definition nodeid. */
+/* "The provided Nodeid was not a type definition nodeid." */
#define UA_STATUSCODE_BADNOTTYPEDEFINITION 0x80C80000
-/* One of the references to follow in the relative path references to a node in the address space in another server. */
+/* "One of the references to follow in the relative path references to a node in the address space in another server." */
#define UA_STATUSCODE_UNCERTAINREFERENCEOUTOFSERVER 0x406C0000
-/* The requested operation has too many matches to return. */
+/* "The requested operation has too many matches to return." */
#define UA_STATUSCODE_BADTOOMANYMATCHES 0x806D0000
-/* The requested operation requires too many resources in the server. */
+/* "The requested operation requires too many resources in the server." */
#define UA_STATUSCODE_BADQUERYTOOCOMPLEX 0x806E0000
-/* The requested operation has no match to return. */
+/* "The requested operation has no match to return." */
#define UA_STATUSCODE_BADNOMATCH 0x806F0000
-/* The max age parameter is invalid. */
+/* "The max age parameter is invalid." */
#define UA_STATUSCODE_BADMAXAGEINVALID 0x80700000
-/* The operation is not permitted over the current secure channel. */
+/* "The operation is not permitted over the current secure channel." */
#define UA_STATUSCODE_BADSECURITYMODEINSUFFICIENT 0x80E60000
-/* The history details parameter is not valid. */
+/* "The history details parameter is not valid." */
#define UA_STATUSCODE_BADHISTORYOPERATIONINVALID 0x80710000
-/* The server does not support the requested operation. */
+/* "The server does not support the requested operation." */
#define UA_STATUSCODE_BADHISTORYOPERATIONUNSUPPORTED 0x80720000
-/* The defined timestamp to return was invalid. */
+/* "The defined timestamp to return was invalid." */
#define UA_STATUSCODE_BADINVALIDTIMESTAMPARGUMENT 0x80BD0000
-/* The server does not support writing the combination of value */
+/* "The server does not support writing the combination of value */
#define UA_STATUSCODE_BADWRITENOTSUPPORTED 0x80730000
-/* The value supplied for the attribute is not of the same type as the attribute's value. */
+/* "The value supplied for the attribute is not of the same type as the attribute's value." */
#define UA_STATUSCODE_BADTYPEMISMATCH 0x80740000
-/* The method id does not refer to a method for the specified object. */
+/* "The method id does not refer to a method for the specified object." */
#define UA_STATUSCODE_BADMETHODINVALID 0x80750000
-/* The client did not specify all of the input arguments for the method. */
+/* "The client did not specify all of the input arguments for the method." */
#define UA_STATUSCODE_BADARGUMENTSMISSING 0x80760000
-/* The executable attribute does not allow the execution of the method. */
+/* "The executable attribute does not allow the execution of the method." */
#define UA_STATUSCODE_BADNOTEXECUTABLE 0x81110000
-/* The server has reached its maximum number of subscriptions. */
+/* "The server has reached its maximum number of subscriptions." */
#define UA_STATUSCODE_BADTOOMANYSUBSCRIPTIONS 0x80770000
-/* The server has reached the maximum number of queued publish requests. */
+/* "The server has reached the maximum number of queued publish requests." */
#define UA_STATUSCODE_BADTOOMANYPUBLISHREQUESTS 0x80780000
-/* There is no subscription available for this session. */
+/* "There is no subscription available for this session." */
#define UA_STATUSCODE_BADNOSUBSCRIPTION 0x80790000
-/* The sequence number is unknown to the server. */
+/* "The sequence number is unknown to the server." */
#define UA_STATUSCODE_BADSEQUENCENUMBERUNKNOWN 0x807A0000
-/* The requested notification message is no longer available. */
+/* "The Server does not support retransmission queue and acknowledgement of sequence numbers is not available." */
+#define UA_STATUSCODE_GOODRETRANSMISSIONQUEUENOTSUPPORTED 0x00DF0000
+
+/* "The requested notification message is no longer available." */
#define UA_STATUSCODE_BADMESSAGENOTAVAILABLE 0x807B0000
-/* The client of the current session does not support one or more Profiles that are necessary for the subscription. */
+/* "The client of the current session does not support one or more Profiles that are necessary for the subscription." */
#define UA_STATUSCODE_BADINSUFFICIENTCLIENTPROFILE 0x807C0000
-/* The sub-state machine is not currently active. */
+/* "The sub-state machine is not currently active." */
#define UA_STATUSCODE_BADSTATENOTACTIVE 0x80BF0000
-/* An equivalent rule already exists. */
+/* "An equivalent rule already exists." */
#define UA_STATUSCODE_BADALREADYEXISTS 0x81150000
-/* The server cannot process the request because it is too busy. */
+/* "The server cannot process the request because it is too busy." */
#define UA_STATUSCODE_BADTCPSERVERTOOBUSY 0x807D0000
-/* The type of the message specified in the header invalid. */
+/* "The type of the message specified in the header invalid." */
#define UA_STATUSCODE_BADTCPMESSAGETYPEINVALID 0x807E0000
-/* The SecureChannelId and/or TokenId are not currently in use. */
+/* "The SecureChannelId and/or TokenId are not currently in use." */
#define UA_STATUSCODE_BADTCPSECURECHANNELUNKNOWN 0x807F0000
-/* The size of the message specified in the header is too large. */
+/* "The size of the message chunk specified in the header is too large." */
#define UA_STATUSCODE_BADTCPMESSAGETOOLARGE 0x80800000
-/* There are not enough resources to process the request. */
+/* "There are not enough resources to process the request." */
#define UA_STATUSCODE_BADTCPNOTENOUGHRESOURCES 0x80810000
-/* An internal error occurred. */
+/* "An internal error occurred." */
#define UA_STATUSCODE_BADTCPINTERNALERROR 0x80820000
-/* The server does not recognize the QueryString specified. */
+/* "The server does not recognize the QueryString specified." */
#define UA_STATUSCODE_BADTCPENDPOINTURLINVALID 0x80830000
-/* The request could not be sent because of a network interruption. */
+/* "The request could not be sent because of a network interruption." */
#define UA_STATUSCODE_BADREQUESTINTERRUPTED 0x80840000
-/* Timeout occurred while processing the request. */
+/* "Timeout occurred while processing the request." */
#define UA_STATUSCODE_BADREQUESTTIMEOUT 0x80850000
-/* The secure channel has been closed. */
+/* "The secure channel has been closed." */
#define UA_STATUSCODE_BADSECURECHANNELCLOSED 0x80860000
-/* The token has expired or is not recognized. */
+/* "The token has expired or is not recognized." */
#define UA_STATUSCODE_BADSECURECHANNELTOKENUNKNOWN 0x80870000
-/* The sequence number is not valid. */
+/* "The sequence number is not valid." */
#define UA_STATUSCODE_BADSEQUENCENUMBERINVALID 0x80880000
-/* The applications do not have compatible protocol versions. */
+/* "The applications do not have compatible protocol versions." */
#define UA_STATUSCODE_BADPROTOCOLVERSIONUNSUPPORTED 0x80BE0000
-/* There is a problem with the configuration that affects the usefulness of the value. */
+/* "There is a problem with the configuration that affects the usefulness of the value." */
#define UA_STATUSCODE_BADCONFIGURATIONERROR 0x80890000
-/* The variable should receive its value from another variable */
+/* "The variable should receive its value from another variable */
#define UA_STATUSCODE_BADNOTCONNECTED 0x808A0000
-/* There has been a failure in the device/data source that generates the value that has affected the value. */
+/* "There has been a failure in the device/data source that generates the value that has affected the value." */
#define UA_STATUSCODE_BADDEVICEFAILURE 0x808B0000
-/* There has been a failure in the sensor from which the value is derived by the device/data source. */
+/* "There has been a failure in the sensor from which the value is derived by the device/data source." */
#define UA_STATUSCODE_BADSENSORFAILURE 0x808C0000
-/* The source of the data is not operational. */
+/* "The source of the data is not operational." */
#define UA_STATUSCODE_BADOUTOFSERVICE 0x808D0000
-/* The deadband filter is not valid. */
+/* "The deadband filter is not valid." */
#define UA_STATUSCODE_BADDEADBANDFILTERINVALID 0x808E0000
-/* Communication to the data source has failed. The variable value is the last value that had a good quality. */
+/* "Communication to the data source has failed. The variable value is the last value that had a good quality." */
#define UA_STATUSCODE_UNCERTAINNOCOMMUNICATIONLASTUSABLEVALUE 0x408F0000
-/* Whatever was updating this value has stopped doing so. */
+/* "Whatever was updating this value has stopped doing so." */
#define UA_STATUSCODE_UNCERTAINLASTUSABLEVALUE 0x40900000
-/* The value is an operational value that was manually overwritten. */
+/* "The value is an operational value that was manually overwritten." */
#define UA_STATUSCODE_UNCERTAINSUBSTITUTEVALUE 0x40910000
-/* The value is an initial value for a variable that normally receives its value from another variable. */
+/* "The value is an initial value for a variable that normally receives its value from another variable." */
#define UA_STATUSCODE_UNCERTAININITIALVALUE 0x40920000
-/* The value is at one of the sensor limits. */
+/* "The value is at one of the sensor limits." */
#define UA_STATUSCODE_UNCERTAINSENSORNOTACCURATE 0x40930000
-/* The value is outside of the range of values defined for this parameter. */
+/* "The value is outside of the range of values defined for this parameter." */
#define UA_STATUSCODE_UNCERTAINENGINEERINGUNITSEXCEEDED 0x40940000
-/* The value is derived from multiple sources and has less than the required number of Good sources. */
+/* "The value is derived from multiple sources and has less than the required number of Good sources." */
#define UA_STATUSCODE_UNCERTAINSUBNORMAL 0x40950000
-/* The value has been overridden. */
+/* "The value has been overridden." */
#define UA_STATUSCODE_GOODLOCALOVERRIDE 0x00960000
-/* This Condition refresh failed */
+/* "This Condition refresh failed */
#define UA_STATUSCODE_BADREFRESHINPROGRESS 0x80970000
-/* This condition has already been disabled. */
+/* "This condition has already been disabled." */
#define UA_STATUSCODE_BADCONDITIONALREADYDISABLED 0x80980000
-/* This condition has already been enabled. */
+/* "This condition has already been enabled." */
#define UA_STATUSCODE_BADCONDITIONALREADYENABLED 0x80CC0000
-/* Property not available */
+/* "Property not available */
#define UA_STATUSCODE_BADCONDITIONDISABLED 0x80990000
-/* The specified event id is not recognized. */
+/* "The specified event id is not recognized." */
#define UA_STATUSCODE_BADEVENTIDUNKNOWN 0x809A0000
-/* The event cannot be acknowledged. */
+/* "The event cannot be acknowledged." */
#define UA_STATUSCODE_BADEVENTNOTACKNOWLEDGEABLE 0x80BB0000
-/* The dialog condition is not active. */
+/* "The dialog condition is not active." */
#define UA_STATUSCODE_BADDIALOGNOTACTIVE 0x80CD0000
-/* The response is not valid for the dialog. */
+/* "The response is not valid for the dialog." */
#define UA_STATUSCODE_BADDIALOGRESPONSEINVALID 0x80CE0000
-/* The condition branch has already been acknowledged. */
+/* "The condition branch has already been acknowledged." */
#define UA_STATUSCODE_BADCONDITIONBRANCHALREADYACKED 0x80CF0000
-/* The condition branch has already been confirmed. */
+/* "The condition branch has already been confirmed." */
#define UA_STATUSCODE_BADCONDITIONBRANCHALREADYCONFIRMED 0x80D00000
-/* The condition has already been shelved. */
+/* "The condition has already been shelved." */
#define UA_STATUSCODE_BADCONDITIONALREADYSHELVED 0x80D10000
-/* The condition is not currently shelved. */
+/* "The condition is not currently shelved." */
#define UA_STATUSCODE_BADCONDITIONNOTSHELVED 0x80D20000
-/* The shelving time not within an acceptable range. */
+/* "The shelving time not within an acceptable range." */
#define UA_STATUSCODE_BADSHELVINGTIMEOUTOFRANGE 0x80D30000
-/* No data exists for the requested time range or event filter. */
+/* "No data exists for the requested time range or event filter." */
#define UA_STATUSCODE_BADNODATA 0x809B0000
-/* No data found to provide upper or lower bound value. */
+/* "No data found to provide upper or lower bound value." */
#define UA_STATUSCODE_BADBOUNDNOTFOUND 0x80D70000
-/* The server cannot retrieve a bound for the variable. */
+/* "The server cannot retrieve a bound for the variable." */
#define UA_STATUSCODE_BADBOUNDNOTSUPPORTED 0x80D80000
-/* Data is missing due to collection started/stopped/lost. */
+/* "Data is missing due to collection started/stopped/lost." */
#define UA_STATUSCODE_BADDATALOST 0x809D0000
-/* Expected data is unavailable for the requested time range due to an un-mounted volume */
+/* "Expected data is unavailable for the requested time range due to an un-mounted volume */
#define UA_STATUSCODE_BADDATAUNAVAILABLE 0x809E0000
-/* The data or event was not successfully inserted because a matching entry exists. */
+/* "The data or event was not successfully inserted because a matching entry exists." */
#define UA_STATUSCODE_BADENTRYEXISTS 0x809F0000
-/* The data or event was not successfully updated because no matching entry exists. */
+/* "The data or event was not successfully updated because no matching entry exists." */
#define UA_STATUSCODE_BADNOENTRYEXISTS 0x80A00000
-/* The client requested history using a timestamp format the server does not support (i.e requested ServerTimestamp when server only supports SourceTimestamp). */
+/* "The client requested history using a timestamp format the server does not support (i.e requested ServerTimestamp when server only supports SourceTimestamp)." */
#define UA_STATUSCODE_BADTIMESTAMPNOTSUPPORTED 0x80A10000
-/* The data or event was successfully inserted into the historical database. */
+/* "The data or event was successfully inserted into the historical database." */
#define UA_STATUSCODE_GOODENTRYINSERTED 0x00A20000
-/* The data or event field was successfully replaced in the historical database. */
+/* "The data or event field was successfully replaced in the historical database." */
#define UA_STATUSCODE_GOODENTRYREPLACED 0x00A30000
-/* The value is derived from multiple values and has less than the required number of Good values. */
+/* "The value is derived from multiple values and has less than the required number of Good values." */
#define UA_STATUSCODE_UNCERTAINDATASUBNORMAL 0x40A40000
-/* No data exists for the requested time range or event filter. */
+/* "No data exists for the requested time range or event filter." */
#define UA_STATUSCODE_GOODNODATA 0x00A50000
-/* The data or event field was successfully replaced in the historical database. */
+/* "The data or event field was successfully replaced in the historical database." */
#define UA_STATUSCODE_GOODMOREDATA 0x00A60000
-/* The requested number of Aggregates does not match the requested number of NodeIds. */
+/* "The requested number of Aggregates does not match the requested number of NodeIds." */
#define UA_STATUSCODE_BADAGGREGATELISTMISMATCH 0x80D40000
-/* The requested Aggregate is not support by the server. */
+/* "The requested Aggregate is not support by the server." */
#define UA_STATUSCODE_BADAGGREGATENOTSUPPORTED 0x80D50000
-/* The aggregate value could not be derived due to invalid data inputs. */
+/* "The aggregate value could not be derived due to invalid data inputs." */
#define UA_STATUSCODE_BADAGGREGATEINVALIDINPUTS 0x80D60000
-/* The aggregate configuration is not valid for specified node. */
+/* "The aggregate configuration is not valid for specified node." */
#define UA_STATUSCODE_BADAGGREGATECONFIGURATIONREJECTED 0x80DA0000
-/* The request specifies fields which are not valid for the EventType or cannot be saved by the historian. */
+/* "The request specifies fields which are not valid for the EventType or cannot be saved by the historian." */
#define UA_STATUSCODE_GOODDATAIGNORED 0x00D90000
-/* The request was rejected by the server because it did not meet the criteria set by the server. */
+/* "The request was rejected by the server because it did not meet the criteria set by the server." */
#define UA_STATUSCODE_BADREQUESTNOTALLOWED 0x80E40000
-/* The request has not been processed by the server yet. */
+/* "The request has not been processed by the server yet." */
#define UA_STATUSCODE_BADREQUESTNOTCOMPLETE 0x81130000
-/* The value does not come from the real source and has been edited by the server. */
+/* "The device identity needs a ticket before it can be accepted." */
+#define UA_STATUSCODE_BADTICKETREQUIRED 0x811F0000
+
+/* "The device identity needs a ticket before it can be accepted." */
+#define UA_STATUSCODE_BADTICKETINVALID 0x81200000
+
+/* "The value does not come from the real source and has been edited by the server." */
#define UA_STATUSCODE_GOODEDITED 0x00DC0000
-/* There was an error in execution of these post-actions. */
+/* "There was an error in execution of these post-actions." */
#define UA_STATUSCODE_GOODPOSTACTIONFAILED 0x00DD0000
-/* The related EngineeringUnit has been changed but the Variable Value is still provided based on the previous unit. */
+/* "The related EngineeringUnit has been changed but the Variable Value is still provided based on the previous unit." */
#define UA_STATUSCODE_UNCERTAINDOMINANTVALUECHANGED 0x40DE0000
-/* A dependent value has been changed but the change has not been applied to the device. */
+/* "A dependent value has been changed but the change has not been applied to the device." */
#define UA_STATUSCODE_GOODDEPENDENTVALUECHANGED 0x00E00000
-/* The related EngineeringUnit has been changed but this change has not been applied to the device. The Variable Value is still dependent on the previous unit but its status is currently Bad. */
+/* "The related EngineeringUnit has been changed but this change has not been applied to the device. The Variable Value is still dependent on the previous unit but its status is currently Bad." */
#define UA_STATUSCODE_BADDOMINANTVALUECHANGED 0x80E10000
-/* A dependent value has been changed but the change has not been applied to the device. The quality of the dominant variable is uncertain. */
+/* "A dependent value has been changed but the change has not been applied to the device. The quality of the dominant variable is uncertain." */
#define UA_STATUSCODE_UNCERTAINDEPENDENTVALUECHANGED 0x40E20000
-/* A dependent value has been changed but the change has not been applied to the device. The quality of the dominant variable is Bad. */
+/* "A dependent value has been changed but the change has not been applied to the device. The quality of the dominant variable is Bad." */
#define UA_STATUSCODE_BADDEPENDENTVALUECHANGED 0x80E30000
-/* The communication layer has raised an event. */
+/* "It is delivered with a dominant Variable value when a dependent Variable has changed but the change has not been applied." */
+#define UA_STATUSCODE_GOODEDITED_DEPENDENTVALUECHANGED 0x01160000
+
+/* "It is delivered with a dependent Variable value when a dominant Variable has changed but the change has not been applied." */
+#define UA_STATUSCODE_GOODEDITED_DOMINANTVALUECHANGED 0x01170000
+
+/* "It is delivered with a dependent Variable value when a dominant or dependent Variable has changed but change has not been applied." */
+#define UA_STATUSCODE_GOODEDITED_DOMINANTVALUECHANGED_DEPENDENTVALUECHANGED 0x01180000
+
+/* "It is delivered with a Variable value when Variable has changed but the value is not legal." */
+#define UA_STATUSCODE_BADEDITED_OUTOFRANGE 0x81190000
+
+/* "It is delivered with a Variable value when a source Variable has changed but the value is not legal." */
+#define UA_STATUSCODE_BADINITIALVALUE_OUTOFRANGE 0x811A0000
+
+/* "It is delivered with a dependent Variable value when a dominant Variable has changed and the value is not legal." */
+#define UA_STATUSCODE_BADOUTOFRANGE_DOMINANTVALUECHANGED 0x811B0000
+
+/* "It is delivered with a dependent Variable value when a dominant Variable has changed */
+#define UA_STATUSCODE_BADEDITED_OUTOFRANGE_DOMINANTVALUECHANGED 0x811C0000
+
+/* "It is delivered with a dependent Variable value when a dominant or dependent Variable has changed and the value is not legal." */
+#define UA_STATUSCODE_BADOUTOFRANGE_DOMINANTVALUECHANGED_DEPENDENTVALUECHANGED 0x811D0000
+
+/* "It is delivered with a dependent Variable value when a dominant or dependent Variable has changed */
+#define UA_STATUSCODE_BADEDITED_OUTOFRANGE_DOMINANTVALUECHANGED_DEPENDENTVALUECHANGED 0x811E0000
+
+/* "The communication layer has raised an event." */
#define UA_STATUSCODE_GOODCOMMUNICATIONEVENT 0x00A70000
-/* The system is shutting down. */
+/* "The system is shutting down." */
#define UA_STATUSCODE_GOODSHUTDOWNEVENT 0x00A80000
-/* The operation is not finished and needs to be called again. */
+/* "The operation is not finished and needs to be called again." */
#define UA_STATUSCODE_GOODCALLAGAIN 0x00A90000
-/* A non-critical timeout occurred. */
+/* "A non-critical timeout occurred." */
#define UA_STATUSCODE_GOODNONCRITICALTIMEOUT 0x00AA0000
-/* One or more arguments are invalid. */
+/* "One or more arguments are invalid." */
#define UA_STATUSCODE_BADINVALIDARGUMENT 0x80AB0000
-/* Could not establish a network connection to remote server. */
+/* "Could not establish a network connection to remote server." */
#define UA_STATUSCODE_BADCONNECTIONREJECTED 0x80AC0000
-/* The server has disconnected from the client. */
+/* "The server has disconnected from the client." */
#define UA_STATUSCODE_BADDISCONNECT 0x80AD0000
-/* The network connection has been closed. */
+/* "The network connection has been closed." */
#define UA_STATUSCODE_BADCONNECTIONCLOSED 0x80AE0000
-/* The operation cannot be completed because the object is closed */
+/* "The operation cannot be completed because the object is closed */
#define UA_STATUSCODE_BADINVALIDSTATE 0x80AF0000
-/* Cannot move beyond end of the stream. */
+/* "Cannot move beyond end of the stream." */
#define UA_STATUSCODE_BADENDOFSTREAM 0x80B00000
-/* No data is currently available for reading from a non-blocking stream. */
+/* "No data is currently available for reading from a non-blocking stream." */
#define UA_STATUSCODE_BADNODATAAVAILABLE 0x80B10000
-/* The asynchronous operation is waiting for a response. */
+/* "The asynchronous operation is waiting for a response." */
#define UA_STATUSCODE_BADWAITINGFORRESPONSE 0x80B20000
-/* The asynchronous operation was abandoned by the caller. */
+/* "The asynchronous operation was abandoned by the caller." */
#define UA_STATUSCODE_BADOPERATIONABANDONED 0x80B30000
-/* The stream did not return all data requested (possibly because it is a non-blocking stream). */
+/* "The stream did not return all data requested (possibly because it is a non-blocking stream)." */
#define UA_STATUSCODE_BADEXPECTEDSTREAMTOBLOCK 0x80B40000
-/* Non blocking behaviour is required and the operation would block. */
+/* "Non blocking behaviour is required and the operation would block." */
#define UA_STATUSCODE_BADWOULDBLOCK 0x80B50000
-/* A value had an invalid syntax. */
+/* "A value had an invalid syntax." */
#define UA_STATUSCODE_BADSYNTAXERROR 0x80B60000
-/* The operation could not be finished because all available connections are in use. */
+/* "The operation could not be finished because all available connections are in use." */
#define UA_STATUSCODE_BADMAXCONNECTIONSREACHED 0x80B70000
+/* Depending on the version of the schema, the following might be already defined: */
+#ifndef UA_STATUSCODE_GOOD
+# define UA_STATUSCODE_GOOD 0x00000000
+#endif
+#ifndef UA_STATUSCODE_UNCERTAIN
+# define UA_STATUSCODE_UNCERTAIN 0x40000000
+#endif
+#ifndef UA_STATUSCODE_BAD
+# define UA_STATUSCODE_BAD 0x80000000
+#endif
+
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/build/src_generated/open62541/nodeids.h" ***********************************/
+/**** amalgamated original file "/build/src_generated/open62541/nodeids.h" ****/
-/*---------------------------------------------------------
- * Autogenerated -- do not modify
- * Generated from /home/pdie/sonstiges/qtopcua/repos/open62541/tools/schema/NodeIds.csv with script /home/pdie/sonstiges/qtopcua/repos/open62541/tools/generate_nodeid_header.py
- *-------------------------------------------------------*/
+/**********************************
+ * Autogenerated -- do not modify *
+ **********************************/
#ifndef UA_NODEIDS_NS0_H_
#define UA_NODEIDS_NS0_H_
@@ -2057,7 +2246,7 @@ UA_atomic_subSize(volatile size_t *addr, size_t decrease) {
* Namespace Zero NodeIds
* ----------------------
* Numeric identifiers of standard-defined nodes in namespace zero. The
- * following definitions are autogenerated from the ``/home/pdie/sonstiges/qtopcua/repos/open62541/tools/schema/NodeIds.csv`` file */
+ * following definitions are autogenerated from a CSV file */
#define UA_NS0ID_BOOLEAN 1 /* DataType */
#define UA_NS0ID_SBYTE 2 /* DataType */
@@ -2123,7 +2312,6 @@ UA_atomic_subSize(volatile size_t *addr, size_t decrease) {
#define UA_NS0ID_DATATYPEENCODINGTYPE 76 /* ObjectType */
#define UA_NS0ID_MODELLINGRULETYPE 77 /* ObjectType */
#define UA_NS0ID_MODELLINGRULE_MANDATORY 78 /* Object */
-#define UA_NS0ID_MODELLINGRULE_MANDATORYSHARED 79 /* Object */
#define UA_NS0ID_MODELLINGRULE_OPTIONAL 80 /* Object */
#define UA_NS0ID_MODELLINGRULE_EXPOSESITSARRAY 83 /* Object */
#define UA_NS0ID_ROOTFOLDER 84 /* Object */
@@ -2153,7 +2341,6 @@ UA_atomic_subSize(volatile size_t *addr, size_t decrease) {
#define UA_NS0ID_MODELLINGRULE_MANDATORY_NAMINGRULE 112 /* Variable */
#define UA_NS0ID_MODELLINGRULE_OPTIONAL_NAMINGRULE 113 /* Variable */
#define UA_NS0ID_MODELLINGRULE_EXPOSESITSARRAY_NAMINGRULE 114 /* Variable */
-#define UA_NS0ID_MODELLINGRULE_MANDATORYSHARED_NAMINGRULE 116 /* Variable */
#define UA_NS0ID_HASSUBSTATEMACHINE 117 /* ReferenceType */
#define UA_NS0ID_NAMINGRULETYPE 120 /* DataType */
#define UA_NS0ID_DATATYPEDEFINITION_ENCODING_DEFAULTBINARY 121 /* Object */
@@ -2202,8 +2389,6 @@ UA_atomic_subSize(volatile size_t *addr, size_t decrease) {
#define UA_NS0ID_COUNTER 289 /* DataType */
#define UA_NS0ID_DURATION 290 /* DataType */
#define UA_NS0ID_NUMERICRANGE 291 /* DataType */
-#define UA_NS0ID_TIME 292 /* DataType */
-#define UA_NS0ID_DATE 293 /* DataType */
#define UA_NS0ID_UTCTIME 294 /* DataType */
#define UA_NS0ID_LOCALEID 295 /* DataType */
#define UA_NS0ID_ARGUMENT 296 /* DataType */
@@ -9202,7 +9387,6 @@ UA_atomic_subSize(volatile size_t *addr, size_t decrease) {
#define UA_NS0ID_SERVER_SERVERCAPABILITIES_ROLESET_ADDROLE_OUTPUTARGUMENTS 16303 /* Variable */
#define UA_NS0ID_SERVER_SERVERCAPABILITIES_ROLESET_REMOVEROLE 16304 /* Method */
#define UA_NS0ID_SERVER_SERVERCAPABILITIES_ROLESET_REMOVEROLE_INPUTARGUMENTS 16305 /* Variable */
-#define UA_NS0ID_DEFAULTINPUTVALUES 16306 /* Variable */
#define UA_NS0ID_AUDIODATATYPE 16307 /* DataType */
#define UA_NS0ID_SUBSCRIBEDDATASETDATATYPE_ENCODING_DEFAULTJSON 16308 /* Object */
#define UA_NS0ID_SELECTIONLISTTYPE 16309 /* VariableType */
@@ -10604,8 +10788,16 @@ UA_atomic_subSize(volatile size_t *addr, size_t decrease) {
#define UA_NS0ID_PROGRAMSTATEMACHINETYPE_AVAILABLETRANSITIONS 17705 /* Variable */
#define UA_NS0ID_PUBLISHSUBSCRIBETYPE_CONNECTIONNAME_PLACEHOLDER_TRANSPORTPROFILEURI_SELECTIONS 17706 /* Variable */
#define UA_NS0ID_PUBLISHSUBSCRIBETYPE_CONNECTIONNAME_PLACEHOLDER_TRANSPORTPROFILEURI_SELECTIONDESCRIPTIONS 17707 /* Variable */
+#define UA_NS0ID_INTERFACETYPES 17708 /* Object */
+#define UA_NS0ID_RATIONALNUMBERTYPE 17709 /* VariableType */
#define UA_NS0ID_PUBSUBCONNECTIONTYPE_TRANSPORTPROFILEURI_SELECTIONS 17710 /* Variable */
#define UA_NS0ID_PUBSUBCONNECTIONTYPE_TRANSPORTPROFILEURI_SELECTIONDESCRIPTIONS 17711 /* Variable */
+#define UA_NS0ID_RATIONALNUMBERTYPE_NUMERATOR 17712 /* Variable */
+#define UA_NS0ID_RATIONALNUMBERTYPE_DENOMINATOR 17713 /* Variable */
+#define UA_NS0ID_VECTORTYPE 17714 /* VariableType */
+#define UA_NS0ID_VECTORTYPE_VECTORUNIT 17715 /* Variable */
+#define UA_NS0ID_THREEDVECTORTYPE 17716 /* VariableType */
+#define UA_NS0ID_THREEDVECTORTYPE_VECTORUNIT 17717 /* Variable */
#define UA_NS0ID_FILEDIRECTORYTYPE_FILEDIRECTORYNAME_PLACEHOLDER_DELETEFILESYSTEMOBJECT 17718 /* Method */
#define UA_NS0ID_FILEDIRECTORYTYPE_FILEDIRECTORYNAME_PLACEHOLDER_DELETEFILESYSTEMOBJECT_INPUTARGUMENTS 17719 /* Variable */
#define UA_NS0ID_PUBSUBCONNECTIONADDREADERGROUPGROUPMETHODTYPE_OUTPUTARGUMENTS 17720 /* Variable */
@@ -10621,7 +10813,6 @@ UA_atomic_subSize(volatile size_t *addr, size_t decrease) {
#define UA_NS0ID_WRITERGROUPTYPE_STATUS 17730 /* Object */
#define UA_NS0ID_WRITERGROUPTYPE_STATUS_STATE 17731 /* Variable */
#define UA_NS0ID_AUTHORIZATIONSERVICES 17732 /* Object */
-#define UA_NS0ID_AUTHORIZATIONSERVICES_SERVICENAME_PLACEHOLDER 17733 /* Object */
#define UA_NS0ID_WRITERGROUPTYPE_STATUS_ENABLE 17734 /* Method */
#define UA_NS0ID_WRITERGROUPTYPE_STATUS_DISABLE 17735 /* Method */
#define UA_NS0ID_WRITERGROUPTYPE_WRITERGROUPID 17736 /* Variable */
@@ -10954,12 +11145,9 @@ UA_atomic_subSize(volatile size_t *addr, size_t decrease) {
#define UA_NS0ID_KEYCREDENTIALDELETEDAUDITEVENTTYPE_INPUTARGUMENTS 18063 /* Variable */
#define UA_NS0ID_KEYCREDENTIALDELETEDAUDITEVENTTYPE_RESOURCEURI 18064 /* Variable */
#define UA_NS0ID_READERGROUPTYPE_MAXNETWORKMESSAGESIZE 18065 /* Variable */
-#define UA_NS0ID_AUTHORIZATIONSERVICES_SERVICENAME_PLACEHOLDER_SERVICECERTIFICATE 18066 /* Variable */
#define UA_NS0ID_READERGROUPTYPE_STATUS 18067 /* Object */
#define UA_NS0ID_READERGROUPTYPE_STATUS_STATE 18068 /* Variable */
#define UA_NS0ID_KEYCREDENTIALCONFIGURATIONTYPE_RESOURCEURI 18069 /* Variable */
-#define UA_NS0ID_AUTHORIZATIONSERVICES_SERVICENAME_PLACEHOLDER_SERVICEURI 18070 /* Variable */
-#define UA_NS0ID_AUTHORIZATIONSERVICES_SERVICENAME_PLACEHOLDER_ISSUERENDPOINTURL 18071 /* Variable */
#define UA_NS0ID_AUTHORIZATIONSERVICECONFIGURATIONTYPE_SERVICEURI 18072 /* Variable */
#define UA_NS0ID_AUTHORIZATIONSERVICECONFIGURATIONTYPE_ISSUERENDPOINTURL 18073 /* Variable */
#define UA_NS0ID_READERGROUPTYPE_STATUS_ENABLE 18074 /* Method */
@@ -11657,6 +11845,108 @@ UA_atomic_subSize(volatile size_t *addr, size_t decrease) {
#define UA_NS0ID_PUBLISHSUBSCRIBETYPE_DIAGNOSTICS_LIVEVALUES_OPERATIONALDATASETWRITERS_DIAGNOSTICSLEVEL 18766 /* Variable */
#define UA_NS0ID_PUBLISHSUBSCRIBETYPE_DIAGNOSTICS_LIVEVALUES_OPERATIONALDATASETREADERS 18767 /* Variable */
#define UA_NS0ID_PUBLISHSUBSCRIBETYPE_DIAGNOSTICS_LIVEVALUES_OPERATIONALDATASETREADERS_DIAGNOSTICSLEVEL 18768 /* Variable */
+#define UA_NS0ID_THREEDVECTORTYPE_X 18769 /* Variable */
+#define UA_NS0ID_THREEDVECTORTYPE_Y 18770 /* Variable */
+#define UA_NS0ID_THREEDVECTORTYPE_Z 18771 /* Variable */
+#define UA_NS0ID_CARTESIANCOORDINATESTYPE 18772 /* VariableType */
+#define UA_NS0ID_CARTESIANCOORDINATESTYPE_LENGTHUNIT 18773 /* Variable */
+#define UA_NS0ID_THREEDCARTESIANCOORDINATESTYPE 18774 /* VariableType */
+#define UA_NS0ID_THREEDCARTESIANCOORDINATESTYPE_LENGTHUNIT 18775 /* Variable */
+#define UA_NS0ID_THREEDCARTESIANCOORDINATESTYPE_X 18776 /* Variable */
+#define UA_NS0ID_THREEDCARTESIANCOORDINATESTYPE_Y 18777 /* Variable */
+#define UA_NS0ID_THREEDCARTESIANCOORDINATESTYPE_Z 18778 /* Variable */
+#define UA_NS0ID_ORIENTATIONTYPE 18779 /* VariableType */
+#define UA_NS0ID_ORIENTATIONTYPE_ANGLEUNIT 18780 /* Variable */
+#define UA_NS0ID_THREEDORIENTATIONTYPE 18781 /* VariableType */
+#define UA_NS0ID_THREEDORIENTATIONTYPE_ANGLEUNIT 18782 /* Variable */
+#define UA_NS0ID_THREEDORIENTATIONTYPE_A 18783 /* Variable */
+#define UA_NS0ID_THREEDORIENTATIONTYPE_B 18784 /* Variable */
+#define UA_NS0ID_THREEDORIENTATIONTYPE_C 18785 /* Variable */
+#define UA_NS0ID_FRAMETYPE 18786 /* VariableType */
+#define UA_NS0ID_FRAMETYPE_ORIENTATION 18787 /* Variable */
+#define UA_NS0ID_FRAMETYPE_CONSTANT 18788 /* Variable */
+#define UA_NS0ID_FRAMETYPE_BASEFRAME 18789 /* Variable */
+#define UA_NS0ID_FRAMETYPE_FIXEDBASE 18790 /* Variable */
+#define UA_NS0ID_THREEDFRAMETYPE 18791 /* VariableType */
+#define UA_NS0ID_THREEDFRAMETYPE_ORIENTATION 18792 /* Variable */
+#define UA_NS0ID_THREEDFRAMETYPE_CONSTANT 18793 /* Variable */
+#define UA_NS0ID_THREEDFRAMETYPE_BASEFRAME 18794 /* Variable */
+#define UA_NS0ID_THREEDFRAMETYPE_FIXEDBASE 18795 /* Variable */
+#define UA_NS0ID_THREEDFRAMETYPE_CARTESIANCOORDINATES 18796 /* Variable */
+#define UA_NS0ID_THREEDFRAMETYPE_CARTESIANCOORDINATES_LENGTHUNIT 18797 /* Variable */
+#define UA_NS0ID_THREEDFRAMETYPE_CARTESIANCOORDINATES_X 18798 /* Variable */
+#define UA_NS0ID_THREEDFRAMETYPE_CARTESIANCOORDINATES_Y 18799 /* Variable */
+#define UA_NS0ID_THREEDFRAMETYPE_CARTESIANCOORDINATES_Z 18800 /* Variable */
+#define UA_NS0ID_FRAMETYPE_CARTESIANCOORDINATES 18801 /* Variable */
+#define UA_NS0ID_FRAMETYPE_CARTESIANCOORDINATES_LENGTHUNIT 18802 /* Variable */
+#define UA_NS0ID_FRAMETYPE_ORIENTATION_ANGLEUNIT 18803 /* Variable */
+#define UA_NS0ID_HASWRITERGROUP 18804 /* ReferenceType */
+#define UA_NS0ID_HASREADERGROUP 18805 /* ReferenceType */
+#define UA_NS0ID_RATIONALNUMBER 18806 /* DataType */
+#define UA_NS0ID_VECTOR 18807 /* DataType */
+#define UA_NS0ID_THREEDVECTOR 18808 /* DataType */
+#define UA_NS0ID_CARTESIANCOORDINATES 18809 /* DataType */
+#define UA_NS0ID_THREEDCARTESIANCOORDINATES 18810 /* DataType */
+#define UA_NS0ID_ORIENTATION 18811 /* DataType */
+#define UA_NS0ID_THREEDORIENTATION 18812 /* DataType */
+#define UA_NS0ID_FRAME 18813 /* DataType */
+#define UA_NS0ID_THREEDFRAME 18814 /* DataType */
+#define UA_NS0ID_RATIONALNUMBER_ENCODING_DEFAULTBINARY 18815 /* Object */
+#define UA_NS0ID_VECTOR_ENCODING_DEFAULTBINARY 18816 /* Object */
+#define UA_NS0ID_THREEDVECTOR_ENCODING_DEFAULTBINARY 18817 /* Object */
+#define UA_NS0ID_CARTESIANCOORDINATES_ENCODING_DEFAULTBINARY 18818 /* Object */
+#define UA_NS0ID_THREEDCARTESIANCOORDINATES_ENCODING_DEFAULTBINARY 18819 /* Object */
+#define UA_NS0ID_ORIENTATION_ENCODING_DEFAULTBINARY 18820 /* Object */
+#define UA_NS0ID_THREEDORIENTATION_ENCODING_DEFAULTBINARY 18821 /* Object */
+#define UA_NS0ID_FRAME_ENCODING_DEFAULTBINARY 18822 /* Object */
+#define UA_NS0ID_THREEDFRAME_ENCODING_DEFAULTBINARY 18823 /* Object */
+#define UA_NS0ID_OPCUA_BINARYSCHEMA_RATIONALNUMBER 18824 /* Variable */
+#define UA_NS0ID_OPCUA_BINARYSCHEMA_RATIONALNUMBER_DATATYPEVERSION 18825 /* Variable */
+#define UA_NS0ID_OPCUA_BINARYSCHEMA_RATIONALNUMBER_DICTIONARYFRAGMENT 18826 /* Variable */
+#define UA_NS0ID_OPCUA_BINARYSCHEMA_VECTOR 18827 /* Variable */
+#define UA_NS0ID_OPCUA_BINARYSCHEMA_VECTOR_DATATYPEVERSION 18828 /* Variable */
+#define UA_NS0ID_OPCUA_BINARYSCHEMA_VECTOR_DICTIONARYFRAGMENT 18829 /* Variable */
+#define UA_NS0ID_OPCUA_BINARYSCHEMA_THREEDVECTOR 18830 /* Variable */
+#define UA_NS0ID_OPCUA_BINARYSCHEMA_THREEDVECTOR_DATATYPEVERSION 18831 /* Variable */
+#define UA_NS0ID_OPCUA_BINARYSCHEMA_THREEDVECTOR_DICTIONARYFRAGMENT 18832 /* Variable */
+#define UA_NS0ID_OPCUA_BINARYSCHEMA_CARTESIANCOORDINATES 18833 /* Variable */
+#define UA_NS0ID_OPCUA_BINARYSCHEMA_CARTESIANCOORDINATES_DATATYPEVERSION 18834 /* Variable */
+#define UA_NS0ID_OPCUA_BINARYSCHEMA_CARTESIANCOORDINATES_DICTIONARYFRAGMENT 18835 /* Variable */
+#define UA_NS0ID_OPCUA_BINARYSCHEMA_THREEDCARTESIANCOORDINATES 18836 /* Variable */
+#define UA_NS0ID_OPCUA_BINARYSCHEMA_THREEDCARTESIANCOORDINATES_DATATYPEVERSION 18837 /* Variable */
+#define UA_NS0ID_OPCUA_BINARYSCHEMA_THREEDCARTESIANCOORDINATES_DICTIONARYFRAGMENT 18838 /* Variable */
+#define UA_NS0ID_OPCUA_BINARYSCHEMA_ORIENTATION 18839 /* Variable */
+#define UA_NS0ID_OPCUA_BINARYSCHEMA_ORIENTATION_DATATYPEVERSION 18840 /* Variable */
+#define UA_NS0ID_OPCUA_BINARYSCHEMA_ORIENTATION_DICTIONARYFRAGMENT 18841 /* Variable */
+#define UA_NS0ID_OPCUA_BINARYSCHEMA_THREEDORIENTATION 18842 /* Variable */
+#define UA_NS0ID_OPCUA_BINARYSCHEMA_THREEDORIENTATION_DATATYPEVERSION 18843 /* Variable */
+#define UA_NS0ID_OPCUA_BINARYSCHEMA_THREEDORIENTATION_DICTIONARYFRAGMENT 18844 /* Variable */
+#define UA_NS0ID_OPCUA_BINARYSCHEMA_FRAME 18845 /* Variable */
+#define UA_NS0ID_OPCUA_BINARYSCHEMA_FRAME_DATATYPEVERSION 18846 /* Variable */
+#define UA_NS0ID_OPCUA_BINARYSCHEMA_FRAME_DICTIONARYFRAGMENT 18847 /* Variable */
+#define UA_NS0ID_OPCUA_BINARYSCHEMA_THREEDFRAME 18848 /* Variable */
+#define UA_NS0ID_OPCUA_BINARYSCHEMA_THREEDFRAME_DATATYPEVERSION 18849 /* Variable */
+#define UA_NS0ID_OPCUA_BINARYSCHEMA_THREEDFRAME_DICTIONARYFRAGMENT 18850 /* Variable */
+#define UA_NS0ID_RATIONALNUMBER_ENCODING_DEFAULTXML 18851 /* Object */
+#define UA_NS0ID_VECTOR_ENCODING_DEFAULTXML 18852 /* Object */
+#define UA_NS0ID_THREEDVECTOR_ENCODING_DEFAULTXML 18853 /* Object */
+#define UA_NS0ID_CARTESIANCOORDINATES_ENCODING_DEFAULTXML 18854 /* Object */
+#define UA_NS0ID_THREEDCARTESIANCOORDINATES_ENCODING_DEFAULTXML 18855 /* Object */
+#define UA_NS0ID_ORIENTATION_ENCODING_DEFAULTXML 18856 /* Object */
+#define UA_NS0ID_THREEDORIENTATION_ENCODING_DEFAULTXML 18857 /* Object */
+#define UA_NS0ID_FRAME_ENCODING_DEFAULTXML 18858 /* Object */
+#define UA_NS0ID_THREEDFRAME_ENCODING_DEFAULTXML 18859 /* Object */
+#define UA_NS0ID_OPCUA_XMLSCHEMA_RATIONALNUMBER 18860 /* Variable */
+#define UA_NS0ID_OPCUA_XMLSCHEMA_RATIONALNUMBER_DATATYPEVERSION 18861 /* Variable */
+#define UA_NS0ID_OPCUA_XMLSCHEMA_RATIONALNUMBER_DICTIONARYFRAGMENT 18862 /* Variable */
+#define UA_NS0ID_OPCUA_XMLSCHEMA_VECTOR 18863 /* Variable */
+#define UA_NS0ID_OPCUA_XMLSCHEMA_VECTOR_DATATYPEVERSION 18864 /* Variable */
+#define UA_NS0ID_OPCUA_XMLSCHEMA_VECTOR_DICTIONARYFRAGMENT 18865 /* Variable */
+#define UA_NS0ID_OPCUA_XMLSCHEMA_THREEDVECTOR 18866 /* Variable */
+#define UA_NS0ID_OPCUA_XMLSCHEMA_THREEDVECTOR_DATATYPEVERSION 18867 /* Variable */
+#define UA_NS0ID_OPCUA_XMLSCHEMA_THREEDVECTOR_DICTIONARYFRAGMENT 18868 /* Variable */
+#define UA_NS0ID_OPCUA_XMLSCHEMA_CARTESIANCOORDINATES 18869 /* Variable */
+#define UA_NS0ID_OPCUA_XMLSCHEMA_CARTESIANCOORDINATES_DATATYPEVERSION 18870 /* Variable */
#define UA_NS0ID_PUBLISHEDDATASETTYPE_DATASETWRITERNAME_PLACEHOLDER_DIAGNOSTICS 18871 /* Object */
#define UA_NS0ID_PUBLISHEDDATASETTYPE_DATASETWRITERNAME_PLACEHOLDER_DIAGNOSTICS_DIAGNOSTICSLEVEL 18872 /* Variable */
#define UA_NS0ID_PUBLISHEDDATASETTYPE_DATASETWRITERNAME_PLACEHOLDER_DIAGNOSTICS_TOTALINFORMATION 18873 /* Variable */
@@ -11834,6 +12124,65 @@ UA_atomic_subSize(volatile size_t *addr, size_t decrease) {
#define UA_NS0ID_PUBLISHEDEVENTSTYPE_DATASETWRITERNAME_PLACEHOLDER_DIAGNOSTICS_LIVEVALUES_MAJORVERSION_DIAGNOSTICSLEVEL 19045 /* Variable */
#define UA_NS0ID_PUBLISHEDEVENTSTYPE_DATASETWRITERNAME_PLACEHOLDER_DIAGNOSTICS_LIVEVALUES_MINORVERSION 19046 /* Variable */
#define UA_NS0ID_PUBLISHEDEVENTSTYPE_DATASETWRITERNAME_PLACEHOLDER_DIAGNOSTICS_LIVEVALUES_MINORVERSION_DIAGNOSTICSLEVEL 19047 /* Variable */
+#define UA_NS0ID_OPCUA_XMLSCHEMA_CARTESIANCOORDINATES_DICTIONARYFRAGMENT 19048 /* Variable */
+#define UA_NS0ID_OPCUA_XMLSCHEMA_THREEDCARTESIANCOORDINATES 19049 /* Variable */
+#define UA_NS0ID_OPCUA_XMLSCHEMA_THREEDCARTESIANCOORDINATES_DATATYPEVERSION 19050 /* Variable */
+#define UA_NS0ID_OPCUA_XMLSCHEMA_THREEDCARTESIANCOORDINATES_DICTIONARYFRAGMENT 19051 /* Variable */
+#define UA_NS0ID_OPCUA_XMLSCHEMA_ORIENTATION 19052 /* Variable */
+#define UA_NS0ID_OPCUA_XMLSCHEMA_ORIENTATION_DATATYPEVERSION 19053 /* Variable */
+#define UA_NS0ID_OPCUA_XMLSCHEMA_ORIENTATION_DICTIONARYFRAGMENT 19054 /* Variable */
+#define UA_NS0ID_OPCUA_XMLSCHEMA_THREEDORIENTATION 19055 /* Variable */
+#define UA_NS0ID_OPCUA_XMLSCHEMA_THREEDORIENTATION_DATATYPEVERSION 19056 /* Variable */
+#define UA_NS0ID_OPCUA_XMLSCHEMA_THREEDORIENTATION_DICTIONARYFRAGMENT 19057 /* Variable */
+#define UA_NS0ID_OPCUA_XMLSCHEMA_FRAME 19058 /* Variable */
+#define UA_NS0ID_OPCUA_XMLSCHEMA_FRAME_DATATYPEVERSION 19059 /* Variable */
+#define UA_NS0ID_OPCUA_XMLSCHEMA_FRAME_DICTIONARYFRAGMENT 19060 /* Variable */
+#define UA_NS0ID_OPCUA_XMLSCHEMA_THREEDFRAME 19061 /* Variable */
+#define UA_NS0ID_OPCUA_XMLSCHEMA_THREEDFRAME_DATATYPEVERSION 19062 /* Variable */
+#define UA_NS0ID_OPCUA_XMLSCHEMA_THREEDFRAME_DICTIONARYFRAGMENT 19063 /* Variable */
+#define UA_NS0ID_RATIONALNUMBER_ENCODING_DEFAULTJSON 19064 /* Object */
+#define UA_NS0ID_VECTOR_ENCODING_DEFAULTJSON 19065 /* Object */
+#define UA_NS0ID_THREEDVECTOR_ENCODING_DEFAULTJSON 19066 /* Object */
+#define UA_NS0ID_CARTESIANCOORDINATES_ENCODING_DEFAULTJSON 19067 /* Object */
+#define UA_NS0ID_THREEDCARTESIANCOORDINATES_ENCODING_DEFAULTJSON 19068 /* Object */
+#define UA_NS0ID_ORIENTATION_ENCODING_DEFAULTJSON 19069 /* Object */
+#define UA_NS0ID_THREEDORIENTATION_ENCODING_DEFAULTJSON 19070 /* Object */
+#define UA_NS0ID_FRAME_ENCODING_DEFAULTJSON 19071 /* Object */
+#define UA_NS0ID_THREEDFRAME_ENCODING_DEFAULTJSON 19072 /* Object */
+#define UA_NS0ID_THREEDFRAMETYPE_ORIENTATION_ANGLEUNIT 19073 /* Variable */
+#define UA_NS0ID_THREEDFRAMETYPE_ORIENTATION_A 19074 /* Variable */
+#define UA_NS0ID_THREEDFRAMETYPE_ORIENTATION_B 19075 /* Variable */
+#define UA_NS0ID_THREEDFRAMETYPE_ORIENTATION_C 19076 /* Variable */
+#define UA_NS0ID_MULTISTATEDICTIONARYENTRYDISCRETEBASETYPE 19077 /* VariableType */
+#define UA_NS0ID_MULTISTATEDICTIONARYENTRYDISCRETEBASETYPE_DEFINITION 19078 /* Variable */
+#define UA_NS0ID_MULTISTATEDICTIONARYENTRYDISCRETEBASETYPE_VALUEPRECISION 19079 /* Variable */
+#define UA_NS0ID_MULTISTATEDICTIONARYENTRYDISCRETEBASETYPE_ENUMVALUES 19080 /* Variable */
+#define UA_NS0ID_MULTISTATEDICTIONARYENTRYDISCRETEBASETYPE_VALUEASTEXT 19081 /* Variable */
+#define UA_NS0ID_MULTISTATEDICTIONARYENTRYDISCRETEBASETYPE_ENUMDICTIONARYENTRIES 19082 /* Variable */
+#define UA_NS0ID_MULTISTATEDICTIONARYENTRYDISCRETEBASETYPE_VALUEASDICTIONARYENTRIES 19083 /* Variable */
+#define UA_NS0ID_MULTISTATEDICTIONARYENTRYDISCRETETYPE 19084 /* VariableType */
+#define UA_NS0ID_MULTISTATEDICTIONARYENTRYDISCRETETYPE_DEFINITION 19085 /* Variable */
+#define UA_NS0ID_MULTISTATEDICTIONARYENTRYDISCRETETYPE_VALUEPRECISION 19086 /* Variable */
+#define UA_NS0ID_MULTISTATEDICTIONARYENTRYDISCRETETYPE_ENUMVALUES 19087 /* Variable */
+#define UA_NS0ID_MULTISTATEDICTIONARYENTRYDISCRETETYPE_VALUEASTEXT 19088 /* Variable */
+#define UA_NS0ID_MULTISTATEDICTIONARYENTRYDISCRETETYPE_ENUMDICTIONARYENTRIES 19089 /* Variable */
+#define UA_NS0ID_MULTISTATEDICTIONARYENTRYDISCRETETYPE_VALUEASDICTIONARYENTRIES 19090 /* Variable */
+#define UA_NS0ID_HISTORYSERVERCAPABILITIES_SERVERTIMESTAMPSUPPORTED 19091 /* Variable */
+#define UA_NS0ID_HISTORICALDATACONFIGURATIONTYPE_SERVERTIMESTAMPSUPPORTED 19092 /* Variable */
+#define UA_NS0ID_HACONFIGURATION_SERVERTIMESTAMPSUPPORTED 19093 /* Variable */
+#define UA_NS0ID_HISTORYSERVERCAPABILITIESTYPE_SERVERTIMESTAMPSUPPORTED 19094 /* Variable */
+#define UA_NS0ID_AUDITHISTORYANNOTATIONUPDATEEVENTTYPE 19095 /* ObjectType */
+#define UA_NS0ID_AUDITHISTORYANNOTATIONUPDATEEVENTTYPE_EVENTID 19096 /* Variable */
+#define UA_NS0ID_AUDITHISTORYANNOTATIONUPDATEEVENTTYPE_EVENTTYPE 19097 /* Variable */
+#define UA_NS0ID_AUDITHISTORYANNOTATIONUPDATEEVENTTYPE_SOURCENODE 19098 /* Variable */
+#define UA_NS0ID_AUDITHISTORYANNOTATIONUPDATEEVENTTYPE_SOURCENAME 19099 /* Variable */
+#define UA_NS0ID_AUDITHISTORYANNOTATIONUPDATEEVENTTYPE_TIME 19100 /* Variable */
+#define UA_NS0ID_AUDITHISTORYANNOTATIONUPDATEEVENTTYPE_RECEIVETIME 19101 /* Variable */
+#define UA_NS0ID_AUDITHISTORYANNOTATIONUPDATEEVENTTYPE_LOCALTIME 19102 /* Variable */
+#define UA_NS0ID_AUDITHISTORYANNOTATIONUPDATEEVENTTYPE_MESSAGE 19103 /* Variable */
+#define UA_NS0ID_AUDITHISTORYANNOTATIONUPDATEEVENTTYPE_SEVERITY 19104 /* Variable */
+#define UA_NS0ID_AUDITHISTORYANNOTATIONUPDATEEVENTTYPE_ACTIONTIMESTAMP 19105 /* Variable */
+#define UA_NS0ID_AUDITHISTORYANNOTATIONUPDATEEVENTTYPE_STATUS 19106 /* Variable */
#define UA_NS0ID_PUBSUBCONNECTIONTYPE_WRITERGROUPNAME_PLACEHOLDER_DIAGNOSTICS 19107 /* Object */
#define UA_NS0ID_PUBSUBCONNECTIONTYPE_WRITERGROUPNAME_PLACEHOLDER_DIAGNOSTICS_DIAGNOSTICSLEVEL 19108 /* Variable */
#define UA_NS0ID_PUBSUBCONNECTIONTYPE_WRITERGROUPNAME_PLACEHOLDER_DIAGNOSTICS_TOTALINFORMATION 19109 /* Variable */
@@ -12016,6 +12365,167 @@ UA_atomic_subSize(volatile size_t *addr, size_t decrease) {
#define UA_NS0ID_PUBSUBCONNECTIONTYPE_DIAGNOSTICS_LIVEVALUES 19286 /* Object */
#define UA_NS0ID_PUBSUBCONNECTIONTYPE_DIAGNOSTICS_LIVEVALUES_RESOLVEDADDRESS 19287 /* Variable */
#define UA_NS0ID_PUBSUBCONNECTIONTYPE_DIAGNOSTICS_LIVEVALUES_RESOLVEDADDRESS_DIAGNOSTICSLEVEL 19288 /* Variable */
+#define UA_NS0ID_AUDITHISTORYANNOTATIONUPDATEEVENTTYPE_SERVERID 19289 /* Variable */
+#define UA_NS0ID_AUDITHISTORYANNOTATIONUPDATEEVENTTYPE_CLIENTAUDITENTRYID 19290 /* Variable */
+#define UA_NS0ID_AUDITHISTORYANNOTATIONUPDATEEVENTTYPE_CLIENTUSERID 19291 /* Variable */
+#define UA_NS0ID_AUDITHISTORYANNOTATIONUPDATEEVENTTYPE_PARAMETERDATATYPEID 19292 /* Variable */
+#define UA_NS0ID_AUDITHISTORYANNOTATIONUPDATEEVENTTYPE_PERFORMINSERTREPLACE 19293 /* Variable */
+#define UA_NS0ID_AUDITHISTORYANNOTATIONUPDATEEVENTTYPE_NEWVALUES 19294 /* Variable */
+#define UA_NS0ID_AUDITHISTORYANNOTATIONUPDATEEVENTTYPE_OLDVALUES 19295 /* Variable */
+#define UA_NS0ID_TRUSTLISTTYPE_UPDATEFREQUENCY 19296 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE 19297 /* ObjectType */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_EVENTID 19298 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_EVENTTYPE 19299 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_SOURCENODE 19300 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_SOURCENAME 19301 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_TIME 19302 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_RECEIVETIME 19303 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_LOCALTIME 19304 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_MESSAGE 19305 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_SEVERITY 19306 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_CONDITIONCLASSID 19307 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_CONDITIONCLASSNAME 19308 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_CONDITIONSUBCLASSID 19309 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_CONDITIONSUBCLASSNAME 19310 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_CONDITIONNAME 19311 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_BRANCHID 19312 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_RETAIN 19313 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_ENABLEDSTATE 19314 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_ENABLEDSTATE_ID 19315 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_ENABLEDSTATE_NAME 19316 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_ENABLEDSTATE_NUMBER 19317 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_ENABLEDSTATE_EFFECTIVEDISPLAYNAME 19318 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_ENABLEDSTATE_TRANSITIONTIME 19319 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_ENABLEDSTATE_EFFECTIVETRANSITIONTIME 19320 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_ENABLEDSTATE_TRUESTATE 19321 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_ENABLEDSTATE_FALSESTATE 19322 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_QUALITY 19323 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_QUALITY_SOURCETIMESTAMP 19324 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_LASTSEVERITY 19325 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_LASTSEVERITY_SOURCETIMESTAMP 19326 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_COMMENT 19327 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_COMMENT_SOURCETIMESTAMP 19328 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_CLIENTUSERID 19329 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_DISABLE 19330 /* Method */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_ENABLE 19331 /* Method */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_ADDCOMMENT 19332 /* Method */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_ADDCOMMENT_INPUTARGUMENTS 19333 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_CONDITIONREFRESH 19334 /* Method */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_CONDITIONREFRESH_INPUTARGUMENTS 19335 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_CONDITIONREFRESH2 19336 /* Method */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_CONDITIONREFRESH2_INPUTARGUMENTS 19337 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_ACKEDSTATE 19338 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_ACKEDSTATE_ID 19339 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_ACKEDSTATE_NAME 19340 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_ACKEDSTATE_NUMBER 19341 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_ACKEDSTATE_EFFECTIVEDISPLAYNAME 19342 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_ACKEDSTATE_TRANSITIONTIME 19343 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_ACKEDSTATE_EFFECTIVETRANSITIONTIME 19344 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_ACKEDSTATE_TRUESTATE 19345 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_ACKEDSTATE_FALSESTATE 19346 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_CONFIRMEDSTATE 19347 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_CONFIRMEDSTATE_ID 19348 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_CONFIRMEDSTATE_NAME 19349 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_CONFIRMEDSTATE_NUMBER 19350 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_CONFIRMEDSTATE_EFFECTIVEDISPLAYNAME 19351 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_CONFIRMEDSTATE_TRANSITIONTIME 19352 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_CONFIRMEDSTATE_EFFECTIVETRANSITIONTIME 19353 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_CONFIRMEDSTATE_TRUESTATE 19354 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_CONFIRMEDSTATE_FALSESTATE 19355 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_ACKNOWLEDGE 19356 /* Method */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_ACKNOWLEDGE_INPUTARGUMENTS 19357 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_CONFIRM 19358 /* Method */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_CONFIRM_INPUTARGUMENTS 19359 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_ACTIVESTATE 19360 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_ACTIVESTATE_ID 19361 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_ACTIVESTATE_NAME 19362 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_ACTIVESTATE_NUMBER 19363 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_ACTIVESTATE_EFFECTIVEDISPLAYNAME 19364 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_ACTIVESTATE_TRANSITIONTIME 19365 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_ACTIVESTATE_EFFECTIVETRANSITIONTIME 19366 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_ACTIVESTATE_TRUESTATE 19367 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_ACTIVESTATE_FALSESTATE 19368 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_INPUTNODE 19369 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_SUPPRESSEDSTATE 19370 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_SUPPRESSEDSTATE_ID 19371 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_SUPPRESSEDSTATE_NAME 19372 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_SUPPRESSEDSTATE_NUMBER 19373 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_SUPPRESSEDSTATE_EFFECTIVEDISPLAYNAME 19374 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_SUPPRESSEDSTATE_TRANSITIONTIME 19375 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_SUPPRESSEDSTATE_EFFECTIVETRANSITIONTIME 19376 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_SUPPRESSEDSTATE_TRUESTATE 19377 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_SUPPRESSEDSTATE_FALSESTATE 19378 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_OUTOFSERVICESTATE 19379 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_OUTOFSERVICESTATE_ID 19380 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_OUTOFSERVICESTATE_NAME 19381 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_OUTOFSERVICESTATE_NUMBER 19382 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_OUTOFSERVICESTATE_EFFECTIVEDISPLAYNAME 19383 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_OUTOFSERVICESTATE_TRANSITIONTIME 19384 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_OUTOFSERVICESTATE_EFFECTIVETRANSITIONTIME 19385 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_OUTOFSERVICESTATE_TRUESTATE 19386 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_OUTOFSERVICESTATE_FALSESTATE 19387 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_SHELVINGSTATE 19388 /* Object */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_SHELVINGSTATE_CURRENTSTATE 19389 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_SHELVINGSTATE_CURRENTSTATE_ID 19390 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_SHELVINGSTATE_CURRENTSTATE_NAME 19391 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_SHELVINGSTATE_CURRENTSTATE_NUMBER 19392 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_SHELVINGSTATE_CURRENTSTATE_EFFECTIVEDISPLAYNAME 19393 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_SHELVINGSTATE_LASTTRANSITION 19394 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_SHELVINGSTATE_LASTTRANSITION_ID 19395 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_SHELVINGSTATE_LASTTRANSITION_NAME 19396 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_SHELVINGSTATE_LASTTRANSITION_NUMBER 19397 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_SHELVINGSTATE_LASTTRANSITION_TRANSITIONTIME 19398 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_SHELVINGSTATE_LASTTRANSITION_EFFECTIVETRANSITIONTIME 19399 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_SHELVINGSTATE_AVAILABLESTATES 19400 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_SHELVINGSTATE_AVAILABLETRANSITIONS 19401 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_SHELVINGSTATE_UNSHELVETIME 19402 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_SHELVINGSTATE_TIMEDSHELVE 19403 /* Method */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_SHELVINGSTATE_TIMEDSHELVE_INPUTARGUMENTS 19404 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_SHELVINGSTATE_UNSHELVE 19405 /* Method */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_SHELVINGSTATE_ONESHOTSHELVE 19406 /* Method */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_SUPPRESSEDORSHELVED 19407 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_MAXTIMESHELVED 19408 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_AUDIBLEENABLED 19409 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_AUDIBLESOUND 19410 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_AUDIBLESOUND_LISTID 19411 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_AUDIBLESOUND_AGENCYID 19412 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_AUDIBLESOUND_VERSIONID 19413 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_SILENCESTATE 19414 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_SILENCESTATE_ID 19415 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_SILENCESTATE_NAME 19416 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_SILENCESTATE_NUMBER 19417 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_SILENCESTATE_EFFECTIVEDISPLAYNAME 19418 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_SILENCESTATE_TRANSITIONTIME 19419 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_SILENCESTATE_EFFECTIVETRANSITIONTIME 19420 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_SILENCESTATE_TRUESTATE 19421 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_SILENCESTATE_FALSESTATE 19422 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_ONDELAY 19423 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_OFFDELAY 19424 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_FIRSTINGROUPFLAG 19425 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_FIRSTINGROUP 19426 /* Object */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_LATCHEDSTATE 19427 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_LATCHEDSTATE_ID 19428 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_LATCHEDSTATE_NAME 19429 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_LATCHEDSTATE_NUMBER 19430 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_LATCHEDSTATE_EFFECTIVEDISPLAYNAME 19431 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_LATCHEDSTATE_TRANSITIONTIME 19432 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_LATCHEDSTATE_EFFECTIVETRANSITIONTIME 19433 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_LATCHEDSTATE_TRUESTATE 19434 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_LATCHEDSTATE_FALSESTATE 19435 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_ALARMGROUP_PLACEHOLDER 19436 /* Object */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_REALARMTIME 19437 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_REALARMREPEATCOUNT 19438 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_SILENCE 19439 /* Method */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_SUPPRESS 19440 /* Method */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_UNSUPPRESS 19441 /* Method */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_REMOVEFROMSERVICE 19442 /* Method */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_PLACEINSERVICE 19443 /* Method */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_RESET 19444 /* Method */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_NORMALSTATE 19445 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_TRUSTLISTID 19446 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_LASTUPDATETIME 19447 /* Variable */
+#define UA_NS0ID_TRUSTLISTOUTOFDATEALARMTYPE_UPDATEFREQUENCY 19448 /* Variable */
+#define UA_NS0ID_CERTIFICATEGROUPTYPE_TRUSTLIST_UPDATEFREQUENCY 19449 /* Variable */
#define UA_NS0ID_DATASETWRITERTYPE_DIAGNOSTICS 19550 /* Object */
#define UA_NS0ID_DATASETWRITERTYPE_DIAGNOSTICS_DIAGNOSTICSLEVEL 19551 /* Variable */
#define UA_NS0ID_DATASETWRITERTYPE_DIAGNOSTICS_TOTALINFORMATION 19552 /* Variable */
@@ -12561,8 +13071,11 @@ UA_atomic_subSize(volatile size_t *addr, size_t decrease) {
#define UA_NS0ID_PUBSUBDIAGNOSTICSDATASETREADERTYPE_LIVEVALUES_SECURITYTOKENID_DIAGNOSTICSLEVEL 20092 /* Variable */
#define UA_NS0ID_PUBSUBDIAGNOSTICSDATASETREADERTYPE_LIVEVALUES_TIMETONEXTTOKENID 20093 /* Variable */
#define UA_NS0ID_PUBSUBDIAGNOSTICSDATASETREADERTYPE_LIVEVALUES_TIMETONEXTTOKENID_DIAGNOSTICSLEVEL 20094 /* Variable */
+#define UA_NS0ID_CERTIFICATEGROUPFOLDERTYPE_DEFAULTAPPLICATIONGROUP_TRUSTLIST_UPDATEFREQUENCY 20290 /* Variable */
#define UA_NS0ID_DATASETORDERINGTYPE 20408 /* DataType */
#define UA_NS0ID_READERGROUPTYPE_DATASETREADERNAME_PLACEHOLDER_DIAGNOSTICS_LIVEVALUES_SECURITYTOKENID 20409 /* Variable */
+#define UA_NS0ID_CERTIFICATEGROUPFOLDERTYPE_DEFAULTHTTPSGROUP_TRUSTLIST_UPDATEFREQUENCY 20588 /* Variable */
+#define UA_NS0ID_CERTIFICATEGROUPFOLDERTYPE_DEFAULTUSERTOKENGROUP_TRUSTLIST_UPDATEFREQUENCY 20884 /* Variable */
#define UA_NS0ID_VERSIONTIME 20998 /* DataType */
#define UA_NS0ID_SESSIONLESSINVOKERESPONSETYPE 20999 /* DataType */
#define UA_NS0ID_SESSIONLESSINVOKERESPONSETYPE_ENCODING_DEFAULTXML 21000 /* Object */
@@ -12766,9 +13279,122 @@ UA_atomic_subSize(volatile size_t *addr, size_t decrease) {
#define UA_NS0ID_READERGROUPDATATYPE_ENCODING_DEFAULTJSON 21201 /* Object */
#define UA_NS0ID_PUBSUBCONFIGURATIONDATATYPE_ENCODING_DEFAULTJSON 21202 /* Object */
#define UA_NS0ID_DATAGRAMWRITERGROUPTRANSPORTDATATYPE_ENCODING_DEFAULTJSON 21203 /* Object */
+#define UA_NS0ID_CERTIFICATEGROUPFOLDERTYPE_ADDITIONALGROUP_PLACEHOLDER_TRUSTLIST_UPDATEFREQUENCY 21383 /* Variable */
+#define UA_NS0ID_SERVERCONFIGURATIONTYPE_CERTIFICATEGROUPS_DEFAULTAPPLICATIONGROUP_TRUSTLIST_UPDATEFREQUENCY 21679 /* Variable */
+#define UA_NS0ID_SERVERCONFIGURATIONTYPE_CERTIFICATEGROUPS_DEFAULTHTTPSGROUP_TRUSTLIST_UPDATEFREQUENCY 21975 /* Variable */
+#define UA_NS0ID_SERVERCONFIGURATIONTYPE_CERTIFICATEGROUPS_DEFAULTUSERTOKENGROUP_TRUSTLIST_UPDATEFREQUENCY 22271 /* Variable */
+#define UA_NS0ID_SERVERCONFIGURATION_CERTIFICATEGROUPS_DEFAULTAPPLICATIONGROUP_TRUSTLIST_UPDATEFREQUENCY 22567 /* Variable */
+#define UA_NS0ID_SERVERCONFIGURATION_CERTIFICATEGROUPS_DEFAULTHTTPSGROUP_TRUSTLIST_UPDATEFREQUENCY 22863 /* Variable */
+#define UA_NS0ID_SERVERCONFIGURATION_CERTIFICATEGROUPS_DEFAULTUSERTOKENGROUP_TRUSTLIST_UPDATEFREQUENCY 23159 /* Variable */
+#define UA_NS0ID_ALIASNAMETYPE 23455 /* ObjectType */
+#define UA_NS0ID_ALIASNAMECATEGORYTYPE 23456 /* ObjectType */
+#define UA_NS0ID_ALIASNAMECATEGORYTYPE_ALIAS_PLACEHOLDER 23457 /* Object */
+#define UA_NS0ID_ALIASNAMECATEGORYTYPE_SUBALIASNAMECATEGORIES_PLACEHOLDER 23458 /* Object */
+#define UA_NS0ID_ALIASNAMECATEGORYTYPE_SUBALIASNAMECATEGORIES_PLACEHOLDER_FINDALIAS 23459 /* Method */
+#define UA_NS0ID_ALIASNAMECATEGORYTYPE_SUBALIASNAMECATEGORIES_PLACEHOLDER_FINDALIAS_INPUTARGUMENTS 23460 /* Variable */
+#define UA_NS0ID_ALIASNAMECATEGORYTYPE_SUBALIASNAMECATEGORIES_PLACEHOLDER_FINDALIAS_OUTPUTARGUMENTS 23461 /* Variable */
+#define UA_NS0ID_ALIASNAMECATEGORYTYPE_FINDALIAS 23462 /* Method */
+#define UA_NS0ID_ALIASNAMECATEGORYTYPE_FINDALIAS_INPUTARGUMENTS 23463 /* Variable */
+#define UA_NS0ID_ALIASNAMECATEGORYTYPE_FINDALIAS_OUTPUTARGUMENTS 23464 /* Variable */
+#define UA_NS0ID_FINDALIASMETHODTYPE 23465 /* Method */
+#define UA_NS0ID_FINDALIASMETHODTYPE_INPUTARGUMENTS 23466 /* Variable */
+#define UA_NS0ID_FINDALIASMETHODTYPE_OUTPUTARGUMENTS 23467 /* Variable */
+#define UA_NS0ID_ALIASNAMEDATATYPE 23468 /* DataType */
+#define UA_NS0ID_ALIASFOR 23469 /* ReferenceType */
+#define UA_NS0ID_ALIASES 23470 /* Object */
+#define UA_NS0ID_ALIASES_ALIAS_PLACEHOLDER 23471 /* Object */
+#define UA_NS0ID_ALIASES_SUBALIASNAMECATEGORIES_PLACEHOLDER 23472 /* Object */
+#define UA_NS0ID_ALIASES_SUBALIASNAMECATEGORIES_PLACEHOLDER_FINDALIAS 23473 /* Method */
+#define UA_NS0ID_ALIASES_SUBALIASNAMECATEGORIES_PLACEHOLDER_FINDALIAS_INPUTARGUMENTS 23474 /* Variable */
+#define UA_NS0ID_ALIASES_SUBALIASNAMECATEGORIES_PLACEHOLDER_FINDALIAS_OUTPUTARGUMENTS 23475 /* Variable */
+#define UA_NS0ID_ALIASES_FINDALIAS 23476 /* Method */
+#define UA_NS0ID_ALIASES_FINDALIAS_INPUTARGUMENTS 23477 /* Variable */
+#define UA_NS0ID_ALIASES_FINDALIAS_OUTPUTARGUMENTS 23478 /* Variable */
+#define UA_NS0ID_TAGVARIABLES 23479 /* Object */
+#define UA_NS0ID_TAGVARIABLES_ALIAS_PLACEHOLDER 23480 /* Object */
+#define UA_NS0ID_TAGVARIABLES_SUBALIASNAMECATEGORIES_PLACEHOLDER 23481 /* Object */
+#define UA_NS0ID_TAGVARIABLES_SUBALIASNAMECATEGORIES_PLACEHOLDER_FINDALIAS 23482 /* Method */
+#define UA_NS0ID_TAGVARIABLES_SUBALIASNAMECATEGORIES_PLACEHOLDER_FINDALIAS_INPUTARGUMENTS 23483 /* Variable */
+#define UA_NS0ID_TAGVARIABLES_SUBALIASNAMECATEGORIES_PLACEHOLDER_FINDALIAS_OUTPUTARGUMENTS 23484 /* Variable */
+#define UA_NS0ID_TAGVARIABLES_FINDALIAS 23485 /* Method */
+#define UA_NS0ID_TAGVARIABLES_FINDALIAS_INPUTARGUMENTS 23486 /* Variable */
+#define UA_NS0ID_TAGVARIABLES_FINDALIAS_OUTPUTARGUMENTS 23487 /* Variable */
+#define UA_NS0ID_TOPICS 23488 /* Object */
+#define UA_NS0ID_TOPICS_ALIAS_PLACEHOLDER 23489 /* Object */
+#define UA_NS0ID_TOPICS_SUBALIASNAMECATEGORIES_PLACEHOLDER 23490 /* Object */
+#define UA_NS0ID_TOPICS_SUBALIASNAMECATEGORIES_PLACEHOLDER_FINDALIAS 23491 /* Method */
+#define UA_NS0ID_TOPICS_SUBALIASNAMECATEGORIES_PLACEHOLDER_FINDALIAS_INPUTARGUMENTS 23492 /* Variable */
+#define UA_NS0ID_TOPICS_SUBALIASNAMECATEGORIES_PLACEHOLDER_FINDALIAS_OUTPUTARGUMENTS 23493 /* Variable */
+#define UA_NS0ID_TOPICS_FINDALIAS 23494 /* Method */
+#define UA_NS0ID_TOPICS_FINDALIAS_INPUTARGUMENTS 23495 /* Variable */
+#define UA_NS0ID_TOPICS_FINDALIAS_OUTPUTARGUMENTS 23496 /* Variable */
+#define UA_NS0ID_READANNOTATIONDATADETAILS 23497 /* DataType */
+#define UA_NS0ID_CURRENCYUNITTYPE 23498 /* DataType */
+#define UA_NS0ID_ALIASNAMEDATATYPE_ENCODING_DEFAULTBINARY 23499 /* Object */
+#define UA_NS0ID_READANNOTATIONDATADETAILS_ENCODING_DEFAULTBINARY 23500 /* Object */
+#define UA_NS0ID_CURRENCYUNIT 23501 /* Variable */
+#define UA_NS0ID_OPCUA_BINARYSCHEMA_ALIASNAMEDATATYPE 23502 /* Variable */
+#define UA_NS0ID_OPCUA_BINARYSCHEMA_ALIASNAMEDATATYPE_DATATYPEVERSION 23503 /* Variable */
+#define UA_NS0ID_OPCUA_BINARYSCHEMA_ALIASNAMEDATATYPE_DICTIONARYFRAGMENT 23504 /* Variable */
+#define UA_NS0ID_ALIASNAMEDATATYPE_ENCODING_DEFAULTXML 23505 /* Object */
+#define UA_NS0ID_READANNOTATIONDATADETAILS_ENCODING_DEFAULTXML 23506 /* Object */
+#define UA_NS0ID_CURRENCYUNITTYPE_ENCODING_DEFAULTBINARY 23507 /* Object */
+#define UA_NS0ID_OPCUA_XMLSCHEMA_ALIASNAMEDATATYPE 23508 /* Variable */
+#define UA_NS0ID_OPCUA_XMLSCHEMA_ALIASNAMEDATATYPE_DATATYPEVERSION 23509 /* Variable */
+#define UA_NS0ID_OPCUA_XMLSCHEMA_ALIASNAMEDATATYPE_DICTIONARYFRAGMENT 23510 /* Variable */
+#define UA_NS0ID_ALIASNAMEDATATYPE_ENCODING_DEFAULTJSON 23511 /* Object */
+#define UA_NS0ID_READANNOTATIONDATADETAILS_ENCODING_DEFAULTJSON 23512 /* Object */
+#define UA_NS0ID_IORDEREDOBJECTTYPE 23513 /* ObjectType */
+#define UA_NS0ID_OPCUA_BINARYSCHEMA_CURRENCYUNITTYPE 23514 /* Variable */
+#define UA_NS0ID_OPCUA_BINARYSCHEMA_CURRENCYUNITTYPE_DATATYPEVERSION 23515 /* Variable */
+#define UA_NS0ID_OPCUA_BINARYSCHEMA_CURRENCYUNITTYPE_DICTIONARYFRAGMENT 23516 /* Variable */
+#define UA_NS0ID_IORDEREDOBJECTTYPE_NUMBERINLIST 23517 /* Variable */
+#define UA_NS0ID_ORDEREDLISTTYPE 23518 /* ObjectType */
+#define UA_NS0ID_ORDEREDLISTTYPE_ORDEREDOBJECT_PLACEHOLDER 23519 /* Object */
+#define UA_NS0ID_CURRENCYUNITTYPE_ENCODING_DEFAULTXML 23520 /* Object */
+#define UA_NS0ID_ORDEREDLISTTYPE_ORDEREDOBJECT_PLACEHOLDER_NUMBERINLIST 23521 /* Variable */
+#define UA_NS0ID_OPCUA_XMLSCHEMA_CURRENCYUNITTYPE 23522 /* Variable */
+#define UA_NS0ID_OPCUA_XMLSCHEMA_CURRENCYUNITTYPE_DATATYPEVERSION 23523 /* Variable */
+#define UA_NS0ID_OPCUA_XMLSCHEMA_CURRENCYUNITTYPE_DICTIONARYFRAGMENT 23524 /* Variable */
+#define UA_NS0ID_ORDEREDLISTTYPE_NODEVERSION 23525 /* Variable */
+#define UA_NS0ID_CERTIFICATEGROUPTYPE_GETREJECTEDLIST 23526 /* Method */
+#define UA_NS0ID_CERTIFICATEGROUPTYPE_GETREJECTEDLIST_OUTPUTARGUMENTS 23527 /* Variable */
+#define UA_NS0ID_CURRENCYUNITTYPE_ENCODING_DEFAULTJSON 23528 /* Object */
+#define UA_NS0ID_CERTIFICATEGROUPFOLDERTYPE_DEFAULTAPPLICATIONGROUP_GETREJECTEDLIST 23529 /* Method */
+#define UA_NS0ID_CERTIFICATEGROUPFOLDERTYPE_DEFAULTAPPLICATIONGROUP_GETREJECTEDLIST_OUTPUTARGUMENTS 23530 /* Variable */
+#define UA_NS0ID_CERTIFICATEGROUPFOLDERTYPE_DEFAULTHTTPSGROUP_GETREJECTEDLIST 23531 /* Method */
+#define UA_NS0ID_CERTIFICATEGROUPFOLDERTYPE_DEFAULTHTTPSGROUP_GETREJECTEDLIST_OUTPUTARGUMENTS 23532 /* Variable */
+#define UA_NS0ID_CERTIFICATEGROUPFOLDERTYPE_DEFAULTUSERTOKENGROUP_GETREJECTEDLIST 23533 /* Method */
+#define UA_NS0ID_CERTIFICATEGROUPFOLDERTYPE_DEFAULTUSERTOKENGROUP_GETREJECTEDLIST_OUTPUTARGUMENTS 23534 /* Variable */
+#define UA_NS0ID_CERTIFICATEGROUPFOLDERTYPE_ADDITIONALGROUP_PLACEHOLDER_GETREJECTEDLIST 23535 /* Method */
+#define UA_NS0ID_CERTIFICATEGROUPFOLDERTYPE_ADDITIONALGROUP_PLACEHOLDER_GETREJECTEDLIST_OUTPUTARGUMENTS 23536 /* Variable */
+#define UA_NS0ID_ECCAPPLICATIONCERTIFICATETYPE 23537 /* ObjectType */
+#define UA_NS0ID_ECCNISTP256APPLICATIONCERTIFICATETYPE 23538 /* ObjectType */
+#define UA_NS0ID_ECCNISTP384APPLICATIONCERTIFICATETYPE 23539 /* ObjectType */
+#define UA_NS0ID_ECCBRAINPOOLP256R1APPLICATIONCERTIFICATETYPE 23540 /* ObjectType */
+#define UA_NS0ID_ECCBRAINPOOLP384R1APPLICATIONCERTIFICATETYPE 23541 /* ObjectType */
+#define UA_NS0ID_ECCCURVE25519APPLICATIONCERTIFICATETYPE 23542 /* ObjectType */
+#define UA_NS0ID_ECCCURVE448APPLICATIONCERTIFICATETYPE 23543 /* ObjectType */
+#define UA_NS0ID_SERVERCONFIGURATIONTYPE_CERTIFICATEGROUPS_DEFAULTAPPLICATIONGROUP_GETREJECTEDLIST 23544 /* Method */
+#define UA_NS0ID_SERVERCONFIGURATIONTYPE_CERTIFICATEGROUPS_DEFAULTAPPLICATIONGROUP_GETREJECTEDLIST_OUTPUTARGUMENTS 23545 /* Variable */
+#define UA_NS0ID_SERVERCONFIGURATIONTYPE_CERTIFICATEGROUPS_DEFAULTHTTPSGROUP_GETREJECTEDLIST 23546 /* Method */
+#define UA_NS0ID_SERVERCONFIGURATIONTYPE_CERTIFICATEGROUPS_DEFAULTHTTPSGROUP_GETREJECTEDLIST_OUTPUTARGUMENTS 23547 /* Variable */
+#define UA_NS0ID_SERVERCONFIGURATIONTYPE_CERTIFICATEGROUPS_DEFAULTUSERTOKENGROUP_GETREJECTEDLIST 23548 /* Method */
+#define UA_NS0ID_SERVERCONFIGURATIONTYPE_CERTIFICATEGROUPS_DEFAULTUSERTOKENGROUP_GETREJECTEDLIST_OUTPUTARGUMENTS 23549 /* Variable */
+#define UA_NS0ID_SERVERCONFIGURATION_CERTIFICATEGROUPS_DEFAULTAPPLICATIONGROUP_GETREJECTEDLIST 23550 /* Method */
+#define UA_NS0ID_SERVERCONFIGURATION_CERTIFICATEGROUPS_DEFAULTAPPLICATIONGROUP_GETREJECTEDLIST_OUTPUTARGUMENTS 23551 /* Variable */
+#define UA_NS0ID_SERVERCONFIGURATION_CERTIFICATEGROUPS_DEFAULTHTTPSGROUP_GETREJECTEDLIST 23552 /* Method */
+#define UA_NS0ID_SERVERCONFIGURATION_CERTIFICATEGROUPS_DEFAULTHTTPSGROUP_GETREJECTEDLIST_OUTPUTARGUMENTS 23553 /* Variable */
+#define UA_NS0ID_SERVERCONFIGURATION_CERTIFICATEGROUPS_DEFAULTUSERTOKENGROUP_GETREJECTEDLIST 23554 /* Method */
+#define UA_NS0ID_SERVERCONFIGURATION_CERTIFICATEGROUPS_DEFAULTUSERTOKENGROUP_GETREJECTEDLIST_OUTPUTARGUMENTS 23555 /* Variable */
+#define UA_NS0ID_AUTHORIZATIONSERVICESCONFIGURATIONFOLDERTYPE 23556 /* ObjectType */
+#define UA_NS0ID_AUTHORIZATIONSERVICESCONFIGURATIONFOLDERTYPE_SERVICENAME_PLACEHOLDER 23557 /* Object */
+#define UA_NS0ID_AUTHORIZATIONSERVICESCONFIGURATIONFOLDERTYPE_SERVICENAME_PLACEHOLDER_SERVICEURI 23558 /* Variable */
+#define UA_NS0ID_AUTHORIZATIONSERVICESCONFIGURATIONFOLDERTYPE_SERVICENAME_PLACEHOLDER_SERVICECERTIFICATE 23559 /* Variable */
+#define UA_NS0ID_AUTHORIZATIONSERVICESCONFIGURATIONFOLDERTYPE_SERVICENAME_PLACEHOLDER_ISSUERENDPOINTURL 23560 /* Variable */
#endif /* UA_NODEIDS_NS0_H_ */
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/include/open62541/common.h" ***********************************/
+/**** amalgamated original file "/include/open62541/common.h" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -12821,7 +13447,11 @@ typedef enum {
UA_ATTRIBUTEID_HISTORIZING = 20,
UA_ATTRIBUTEID_EXECUTABLE = 21,
UA_ATTRIBUTEID_USEREXECUTABLE = 22,
- UA_ATTRIBUTEID_DATATYPEDEFINITION = 23
+ UA_ATTRIBUTEID_DATATYPEDEFINITION = 23,
+ UA_ATTRIBUTEID_ROLEPERMISSIONS = 24,
+ UA_ATTRIBUTEID_USERROLEPERMISSIONS = 25,
+ UA_ATTRIBUTEID_ACCESSRESTRICTIONS = 26,
+ UA_ATTRIBUTEID_ACCESSLEVELEX = 27
} UA_AttributeId;
/**
@@ -12883,6 +13513,20 @@ typedef enum {
#define UA_VALUERANK_THREE_DIMENSIONS 3
/**
+ * EventNotifier
+ * -------------
+ * The following are the available EventNotifier used for Nodes.
+ * The EventNotifier Attribute is used to indicate if the Node can be used
+ * to subscribe to Events or to read / write historic Events.
+ * Part 3: 5.4 Table 10 */
+
+#define UA_EVENTNOTIFIER_SUBSCRIBE_TO_EVENT (0x01u << 0u)
+#define UA_EVENTNOTIFIER_HISTORY_READ (0x01u << 2u)
+#define UA_EVENTNOTIFIER_HISTORY_WRITE (0x01u << 3u)
+
+/**
+ * .. _rule-handling:
+ *
* Rule Handling
* -------------
*
@@ -12916,14 +13560,15 @@ typedef enum {
* ---------------- */
typedef enum {
- UA_SECURECHANNELSTATE_CLOSED,
+ UA_SECURECHANNELSTATE_FRESH = 0,
UA_SECURECHANNELSTATE_HEL_SENT,
UA_SECURECHANNELSTATE_HEL_RECEIVED,
UA_SECURECHANNELSTATE_ACK_SENT,
UA_SECURECHANNELSTATE_ACK_RECEIVED,
UA_SECURECHANNELSTATE_OPN_SENT,
UA_SECURECHANNELSTATE_OPEN,
- UA_SECURECHANNELSTATE_CLOSING
+ UA_SECURECHANNELSTATE_CLOSING,
+ UA_SECURECHANNELSTATE_CLOSED
} UA_SecureChannelState;
typedef enum {
@@ -12939,7 +13584,7 @@ typedef enum {
* Statistic counters
* ------------------
*
- * The stack manage statistic counter for the following layers:
+ * The stack manages statistic counters for the following layers:
*
* - Network
* - Secure channel
@@ -12947,7 +13592,7 @@ typedef enum {
*
* The session layer counters are matching the counters of the
* ServerDiagnosticsSummaryDataType that are defined in the OPC UA Part 5
- * specification. Counter of the other layers are not specified by OPC UA but
+ * specification. Counters of the other layers are not specified by OPC UA but
* are harmonized with the session layer counters if possible. */
typedef struct {
@@ -12982,7 +13627,7 @@ typedef struct {
_UA_END_DECLS
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/include/open62541/types.h" ***********************************/
+/**** amalgamated original file "/include/open62541/types.h" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -13003,8 +13648,6 @@ _UA_END_DECLS
_UA_BEGIN_DECLS
-#define UA_BUILTIN_TYPES_COUNT 25U
-
/**
* .. _types:
*
@@ -13113,9 +13756,19 @@ typedef double UA_Double;
*
* StatusCode
* ^^^^^^^^^^
- * A numeric identifier for a error or condition that is associated with a value
- * or an operation. See the section :ref:`statuscodes` for the meaning of a
- * specific code. */
+ * A numeric identifier for an error or condition that is associated with a
+ * value or an operation. See the section :ref:`statuscodes` for the meaning of
+ * a specific code.
+ *
+ * Each StatusCode has one of three "severity" bit-flags:
+ * Good, Uncertain, Bad. An additional reason is indicated by the SubCode
+ * bitfield.
+ *
+ * - A StatusCode with severity Good means that the value is of good quality.
+ * - A StatusCode with severity Uncertain means that the quality of the value is
+ * uncertain for reasons indicated by the SubCode.
+ * - A StatusCode with severity Bad means that the value is not usable for
+ * reasons indicated by the SubCode. */
typedef uint32_t UA_StatusCode;
/* Returns the human-readable name of the StatusCode. If no matching StatusCode
@@ -13126,6 +13779,32 @@ typedef uint32_t UA_StatusCode;
UA_EXPORT const char *
UA_StatusCode_name(UA_StatusCode code);
+/* Extracts the severity from a StatusCode. See Part 4, Section 7.34 for
+ * details. */
+static UA_INLINE UA_Boolean
+UA_StatusCode_isBad(UA_StatusCode code) {
+ return ((code >> 30) >= 0x02);
+}
+
+static UA_INLINE UA_Boolean
+UA_StatusCode_isUncertain(UA_StatusCode code) {
+ return ((code >> 30) == 0x01);
+}
+
+static UA_INLINE UA_Boolean
+UA_StatusCode_isGood(UA_StatusCode code) {
+ return ((code >> 30) == 0x00);
+}
+
+/* Compares the top 16 bits of two StatusCodes for equality. This should only
+ * be used when processing user-defined StatusCodes e.g when processing a ReadResponse.
+ * As a convention, the lower bits of StatusCodes should not be used internally, meaning
+ * can compare them without the use of this function. */
+static UA_INLINE UA_Boolean
+UA_StatusCode_isEqualTop (UA_StatusCode s1, UA_StatusCode s2) {
+ return ((s1 & 0xFFFF0000) == (s2 & 0xFFFF0000));
+}
+
/**
* String
* ^^^^^^
@@ -13204,7 +13883,7 @@ typedef struct UA_DateTimeStruct {
UA_UInt16 hour;
UA_UInt16 day; /* From 1 to 31 */
UA_UInt16 month; /* From 1 to 12 */
- UA_UInt16 year;
+ UA_Int16 year; /* Can be negative (BC) */
} UA_DateTimeStruct;
UA_DateTimeStruct UA_EXPORT UA_DateTime_toStruct(UA_DateTime t);
@@ -13304,9 +13983,7 @@ UA_ByteString_equal(const UA_ByteString *string1,
(const UA_String*)string2);
}
-/* Returns a non-cryptographic hash for the String.
- * Uses FNV non-cryptographic hash function. See
- * https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function */
+/* Returns a non-cryptographic hash of a bytestring */
UA_UInt32 UA_EXPORT
UA_ByteString_hash(UA_UInt32 initialHashValue,
const UA_Byte *data, size_t size);
@@ -13443,6 +14120,9 @@ typedef struct {
UA_EXPORT extern const UA_ExpandedNodeId UA_EXPANDEDNODEID_NULL;
+UA_StatusCode UA_EXPORT
+UA_ExpandedNodeId_print(const UA_ExpandedNodeId *id, UA_String *output);
+
#ifdef UA_ENABLE_PARSING
/* Parse the ExpandedNodeId format defined in Part 6, 5.3.1.11:
*
@@ -13500,18 +14180,33 @@ UA_EXPANDEDNODEID_BYTESTRING_ALLOC(UA_UInt16 nsIndex, const char *chars) {
id.serverIndex = 0; id.namespaceUri = UA_STRING_NULL; return id;
}
+static UA_INLINE UA_ExpandedNodeId
+UA_EXPANDEDNODEID_NODEID(UA_NodeId nodeId) {
+ UA_ExpandedNodeId id = {0}; id.nodeId = nodeId; return id;
+}
+
+/* Does the ExpandedNodeId point to a local node? That is, are namespaceUri and
+ * serverIndex empty? */
+UA_Boolean UA_EXPORT
+UA_ExpandedNodeId_isLocal(const UA_ExpandedNodeId *n);
+
/* Total ordering of ExpandedNodeId */
UA_Order UA_EXPORT
-UA_ExpandedNodeId_order(const UA_ExpandedNodeId *n1, const UA_ExpandedNodeId *n2);
+UA_ExpandedNodeId_order(const UA_ExpandedNodeId *n1,
+ const UA_ExpandedNodeId *n2);
/* Check for equality */
static UA_INLINE UA_Boolean
-UA_ExpandedNodeId_equal(const UA_ExpandedNodeId *n1, const UA_ExpandedNodeId *n2) {
+UA_ExpandedNodeId_equal(const UA_ExpandedNodeId *n1,
+ const UA_ExpandedNodeId *n2) {
return (UA_ExpandedNodeId_order(n1, n2) == UA_ORDER_EQ);
}
-/* Returns a non-cryptographic hash for ExpandedNodeId */
-UA_UInt32 UA_EXPORT UA_ExpandedNodeId_hash(const UA_ExpandedNodeId *n);
+/* Returns a non-cryptographic hash for ExpandedNodeId. The hash of an
+ * ExpandedNodeId is identical to the hash of the embedded (simple) NodeId if
+ * the ServerIndex is zero and no NamespaceUri is set. */
+UA_UInt32 UA_EXPORT
+UA_ExpandedNodeId_hash(const UA_ExpandedNodeId *n);
/**
* .. _qualifiedname:
@@ -13600,11 +14295,6 @@ UA_NUMERICRANGE(const char *s) {
UA_NumericRange_parse(&nr, UA_STRING((char*)(uintptr_t)s)); return nr;
}
-UA_DEPRECATED static UA_INLINE UA_StatusCode
-UA_NumericRange_parseFromString(UA_NumericRange *range, const UA_String *str) {
- return UA_NumericRange_parse(range, *str);
-}
-
/**
* .. _variant:
*
@@ -13646,11 +14336,10 @@ typedef struct UA_DataType UA_DataType;
#define UA_EMPTY_ARRAY_SENTINEL ((void*)0x01)
typedef enum {
- UA_VARIANT_DATA, /* The data has the same lifecycle as the
- variant */
- UA_VARIANT_DATA_NODELETE /* The data is "borrowed" by the variant and
- shall not be deleted at the end of the
- variant's lifecycle. */
+ UA_VARIANT_DATA, /* The data has the same lifecycle as the variant */
+ UA_VARIANT_DATA_NODELETE /* The data is "borrowed" by the variant and is
+ * not deleted when the variant is cleared up.
+ * The array dimensions also borrowed. */
} UA_VariantStorageType;
typedef struct {
@@ -13718,7 +14407,7 @@ UA_Variant_setScalar(UA_Variant *v, void * UA_RESTRICT p,
* @param type The datatype of the value
* @return Indicates whether the operation succeeded or returns an error code */
UA_StatusCode UA_EXPORT
-UA_Variant_setScalarCopy(UA_Variant *v, const void *p,
+UA_Variant_setScalarCopy(UA_Variant *v, const void * UA_RESTRICT p,
const UA_DataType *type);
/* Set the variant to an array that already resides in memory. The array takes
@@ -13740,7 +14429,7 @@ UA_Variant_setArray(UA_Variant *v, void * UA_RESTRICT array,
* @param type The datatype of the array
* @return Indicates whether the operation succeeded or returns an error code */
UA_StatusCode UA_EXPORT
-UA_Variant_setArrayCopy(UA_Variant *v, const void *array,
+UA_Variant_setArrayCopy(UA_Variant *v, const void * UA_RESTRICT array,
size_t arraySize, const UA_DataType *type);
/* Copy the variant, but use only a subset of the (multidimensional) array into
@@ -13752,10 +14441,10 @@ UA_Variant_setArrayCopy(UA_Variant *v, const void *array,
* @param range The range of the copied data
* @return Returns UA_STATUSCODE_GOOD or an error code */
UA_StatusCode UA_EXPORT
-UA_Variant_copyRange(const UA_Variant *src, UA_Variant *dst,
+UA_Variant_copyRange(const UA_Variant *src, UA_Variant * UA_RESTRICT dst,
const UA_NumericRange range);
-/* Insert a range of data into an existing variant. The data array can't be
+/* Insert a range of data into an existing variant. The data array cannot be
* reused afterwards if it contains types without a fixed size (e.g. strings)
* since the members are moved into the variant and take on its lifecycle.
*
@@ -13778,7 +14467,7 @@ UA_Variant_setRange(UA_Variant *v, void * UA_RESTRICT array,
* @param range The range of where the new data is inserted
* @return Returns UA_STATUSCODE_GOOD or an error code */
UA_StatusCode UA_EXPORT
-UA_Variant_setRangeCopy(UA_Variant *v, const void *array,
+UA_Variant_setRangeCopy(UA_Variant *v, const void * UA_RESTRICT array,
size_t arraySize, const UA_NumericRange range);
/**
@@ -13815,6 +14504,29 @@ typedef struct {
} content;
} UA_ExtensionObject;
+/* Initialize the ExtensionObject and set the "decoded" value to the given
+ * pointer. The value will be deleted when the ExtensionObject is cleared. */
+void UA_EXPORT
+UA_ExtensionObject_setValue(UA_ExtensionObject *eo,
+ void * UA_RESTRICT p,
+ const UA_DataType *type);
+
+/* Initialize the ExtensionObject and set the "decoded" value to the given
+ * pointer. The value will *not* be deleted when the ExtensionObject is
+ * cleared. */
+void UA_EXPORT
+UA_ExtensionObject_setValueNoDelete(UA_ExtensionObject *eo,
+ void * UA_RESTRICT p,
+ const UA_DataType *type);
+
+/* Initialize the ExtensionObject and set the "decoded" value to a fresh copy of
+ * the given value pointer. The value will be deleted when the ExtensionObject
+ * is cleared. */
+UA_StatusCode UA_EXPORT
+UA_ExtensionObject_setValueCopy(UA_ExtensionObject *eo,
+ void * UA_RESTRICT p,
+ const UA_DataType *type);
+
/**
* .. _datavalue:
*
@@ -13836,6 +14548,18 @@ typedef struct {
UA_Boolean hasServerPicoseconds : 1;
} UA_DataValue;
+/* Copy the DataValue, but use only a subset of the (multidimensional) array of
+ * of the variant of the source DataValue. Returns an error code if the variant
+ * of the DataValue is not an array or if the indicated range does not fit.
+ *
+ * @param src The source DataValue
+ * @param dst The target DataValue
+ * @param range The range of the variant of the DataValue to copy
+ * @return Returns UA_STATUSCODE_GOOD or an error code */
+UA_StatusCode UA_EXPORT
+UA_DataValue_copyVariantRange(const UA_DataValue *src, UA_DataValue * UA_RESTRICT dst,
+ const UA_NumericRange range);
+
/**
* DiagnosticInfo
* ^^^^^^^^^^^^^^
@@ -13886,22 +14610,19 @@ typedef struct UA_DiagnosticInfo {
typedef struct {
#ifdef UA_ENABLE_TYPEDESCRIPTION
- const char *memberName;
+ const char *memberName; /* Human-readable member name */
#endif
- UA_UInt16 memberTypeIndex; /* Index of the member in the array of data
- types */
- UA_Byte padding; /* How much padding is there before this
+ const UA_DataType *memberType;/* The member data type description */
+ UA_Byte padding : 6; /* How much padding is there before this
member element? For arrays this is the
padding before the size_t length member.
(No padding between size_t and the
- following ptr.) */
- UA_Boolean namespaceZero : 1; /* The type of the member is defined in
- namespace zero. In this implementation,
- types from custom namespace may contain
- members from the same namespace or
- namespace zero only.*/
- UA_Boolean isArray : 1; /* The member is an array */
- UA_Boolean isOptional : 1; /* The member is an optional field */
+ following ptr.) For unions, the padding
+ includes the size of the switchfield (the
+ offset from the start of the union
+ type). */
+ UA_Byte isArray : 1; /* The member is an array */
+ UA_Byte isOptional : 1; /* The member is an optional field */
} UA_DataTypeMember;
/* The DataType "kind" is an internal type classification. It is used to
@@ -13945,26 +14666,52 @@ struct UA_DataType {
#ifdef UA_ENABLE_TYPEDESCRIPTION
const char *typeName;
#endif
- UA_NodeId typeId; /* The nodeid of the type */
- UA_UInt16 memSize; /* Size of the struct in memory */
- UA_UInt16 typeIndex; /* Index of the type in the datatypetable */
- UA_UInt32 typeKind : 6; /* Dispatch index for the handling routines */
- UA_UInt32 pointerFree : 1; /* The type (and its members) contains no
- * pointers that need to be freed */
- UA_UInt32 overlayable : 1; /* The type has the identical memory layout
- * in memory and on the binary stream. */
- UA_UInt32 membersSize : 8; /* How many members does the type have? */
- UA_UInt32 binaryEncodingId; /* NodeId of datatype when encoded as binary */
- //UA_UInt16 xmlEncodingId; /* NodeId of datatype when encoded as XML */
+ UA_NodeId typeId; /* The nodeid of the type */
+ UA_NodeId binaryEncodingId; /* NodeId of datatype when encoded as binary */
+ //UA_NodeId xmlEncodingId; /* NodeId of datatype when encoded as XML */
+ UA_UInt32 memSize : 16; /* Size of the struct in memory */
+ UA_UInt32 typeKind : 6; /* Dispatch index for the handling routines */
+ UA_UInt32 pointerFree : 1; /* The type (and its members) contains no
+ * pointers that need to be freed */
+ UA_UInt32 overlayable : 1; /* The type has the identical memory layout
+ * in memory and on the binary stream. */
+ UA_UInt32 membersSize : 8; /* How many members does the type have? */
UA_DataTypeMember *members;
};
-/* Test if the data type is a numeric builtin data type. This includes Boolean,
- * integers and floating point numbers. Not included are DateTime and
- * StatusCode. */
+/* Datatype arrays with custom type definitions can be added in a linked list to
+ * the client or server configuration. */
+typedef struct UA_DataTypeArray {
+ const struct UA_DataTypeArray *next;
+ const size_t typesSize;
+ const UA_DataType *types;
+} UA_DataTypeArray;
+
+/* Returns the offset and type of a structure member. The return value is false
+ * if the member was not found.
+ *
+ * If the member is an array, the offset points to the (size_t) length field.
+ * (The array pointer comes after the length field without any padding.) */
+#ifdef UA_ENABLE_TYPEDESCRIPTION
+UA_Boolean
+UA_DataType_getStructMember(const UA_DataType *type,
+ const char *memberName,
+ size_t *outOffset,
+ const UA_DataType **outMemberType,
+ UA_Boolean *outIsArray);
+#endif
+
+/* Test if the data type is a numeric builtin data type (via the typeKind field
+ * of UA_DataType). This includes integers and floating point numbers. Not
+ * included are Boolean, DateTime, StatusCode and Enums. */
UA_Boolean
UA_DataType_isNumeric(const UA_DataType *type);
+/* Return the Data Type Precedence-Rank defined in Part 4.
+ * If there is no Precedence-Rank assigned with the type -1 is returned.*/
+UA_Int16
+UA_DataType_getPrecedence(const UA_DataType *type);
+
/**
* Builtin data types can be accessed as UA_TYPES[UA_TYPES_XXX], where XXX is
* the name of the data type. If only the NodeId of a type is known, use the
@@ -14021,6 +14768,130 @@ void UA_EXPORT UA_clear(void *p, const UA_DataType *type);
* @param type The datatype description of the variable */
void UA_EXPORT UA_delete(void *p, const UA_DataType *type);
+/* Pretty-print the value from the datatype.
+ *
+ * @param p The memory location of the variable
+ * @param type The datatype description of the variable
+ * @param output A string that is memory-allocated for the pretty-printed output
+ * @return Indicates whether the operation succeeded*/
+#ifdef UA_ENABLE_TYPEDESCRIPTION
+UA_StatusCode UA_EXPORT
+UA_print(const void *p, const UA_DataType *type, UA_String *output);
+#endif
+
+/* Compare two variables and return their order. This can also be used to test
+ * for equality of two values.
+ *
+ * For numerical types (including StatusCodes and Enums), their natural order is
+ * used. NaN is the "smallest" value for floating point values. Different bit
+ * representations of NaN are considered identical.
+ *
+ * All other types have *some* absolute ordering so that a < b, b < c -> a < c.
+ *
+ * The ordering of arrays (also strings) is in "shortlex": A shorter array is
+ * always smaller than a longer array. Otherwise the first different element
+ * defines the order.
+ *
+ * When members of different types are permitted (in Variants and
+ * ExtensionObjects), the memory address in the "UA_DataType*" pointer
+ * determines which variable is smaller.
+ *
+ * @param p1 The memory location of the first value
+ * @param p2 The memory location of the first value
+ * @param type The datatype description of both values */
+UA_Order UA_EXPORT
+UA_order(const void *p1, const void *p2, const UA_DataType *type);
+
+/**
+ * Encoding/Decoding
+ * ^^^^^^^^^^^^^^^^^^
+ * Encoding and decoding routines for the available formats. For all formats
+ * the _calcSize, _encode and _decode methods are provided. */
+
+/* Returns the number of bytes the value p takes in binary encoding. Returns
+ * zero if an error occurs. */
+UA_EXPORT size_t
+UA_calcSizeBinary(const void *p, const UA_DataType *type);
+
+/* Encodes a data-structure in the binary format. If outBuf has a length of
+ * zero, a buffer of the required size is allocated. Otherwise, encoding into
+ * the existing outBuf is attempted (and may fail if the buffer is too
+ * small). */
+UA_EXPORT UA_StatusCode
+UA_encodeBinary(const void *p, const UA_DataType *type,
+ UA_ByteString *outBuf);
+
+/* The structure with the decoding options may be extended in the future.
+ * Zero-out the entire structure initially to ensure code-compatibility when
+ * more fields are added in a later release. */
+typedef struct {
+ const UA_DataTypeArray *customTypes; /* Begin of a linked list with custom
+ * datatype definitions */
+} UA_DecodeBinaryOptions;
+
+/* Decodes a data structure from the input buffer in the binary format. It is
+ * assumed that `p` points to valid memory (not necessarily zeroed out). The
+ * options can be NULL and will be disregarded in that case. */
+UA_EXPORT UA_StatusCode
+UA_decodeBinary(const UA_ByteString *inBuf,
+ void *p, const UA_DataType *type,
+ const UA_DecodeBinaryOptions *options);
+
+#ifdef UA_ENABLE_JSON_ENCODING
+
+typedef struct {
+ const UA_String *namespaces;
+ size_t namespacesSize;
+ const UA_String *serverUris;
+ size_t serverUrisSize;
+ UA_Boolean useReversible;
+} UA_EncodeJsonOptions;
+
+/* Returns the number of bytes the value src takes in json encoding. Returns
+ * zero if an error occurs. */
+UA_EXPORT size_t
+UA_calcSizeJson(const void *src, const UA_DataType *type,
+ const UA_EncodeJsonOptions *options);
+
+/* Encodes the scalar value described by type to json encoding.
+ *
+ * @param src The value. Must not be NULL.
+ * @param type The value type. Must not be NULL.
+ * @param outBuf Pointer to ByteString containing the result if the encoding
+ * was successful
+ * @return Returns a statuscode whether encoding succeeded. */
+UA_StatusCode UA_EXPORT
+UA_encodeJson(const void *src, const UA_DataType *type, UA_ByteString *outBuf,
+ const UA_EncodeJsonOptions *options);
+
+/* The structure with the decoding options may be extended in the future.
+ * Zero-out the entire structure initially to ensure code-compatibility when
+ * more fields are added in a later release. */
+typedef struct {
+ const UA_String *namespaces;
+ size_t namespacesSize;
+ const UA_String *serverUris;
+ size_t serverUrisSize;
+ const UA_DataTypeArray *customTypes; /* Begin of a linked list with custom
+ * datatype definitions */
+} UA_DecodeJsonOptions;
+
+/* Decodes a scalar value described by type from json encoding.
+ *
+ * @param src The buffer with the json encoded value. Must not be NULL.
+ * @param dst The target value. Must not be NULL. The target is assumed to have
+ * size type->memSize. The value is reset to zero before decoding. If
+ * decoding fails, members are deleted and the value is reset (zeroed)
+ * again.
+ * @param type The value type. Must not be NULL.
+ * @param options The options struct for decoding, currently unused
+ * @return Returns a statuscode whether decoding succeeded. */
+UA_StatusCode UA_EXPORT
+UA_decodeJson(const UA_ByteString *src, void *dst, const UA_DataType *type,
+ const UA_DecodeJsonOptions *options);
+
+#endif /* UA_ENABLE_JSON_ENCODING */
+
/**
* .. _array-handling:
*
@@ -14039,7 +14910,7 @@ void UA_EXPORT UA_delete(void *p, const UA_DataType *type);
* @param size The requested array length
* @param type The datatype description
* @return Returns the memory location of the variable or NULL if no memory
- could be allocated */
+ * could be allocated */
void UA_EXPORT *
UA_Array_new(size_t size, const UA_DataType *type) UA_FUNC_ATTR_MALLOC;
@@ -14054,12 +14925,57 @@ UA_StatusCode UA_EXPORT
UA_Array_copy(const void *src, size_t size, void **dst,
const UA_DataType *type) UA_FUNC_ATTR_WARN_UNUSED_RESULT;
+/* Resizes (and reallocates) an array. The last entries are initialized to zero
+ * if the array length is increased. If the array length is decreased, the last
+ * entries are removed if the size is decreased.
+ *
+ * @param p Double pointer to the array memory. Can be overwritten by the result
+ * of a realloc.
+ * @param size The current size of the array. Overwritten in case of success.
+ * @param newSize The new size of the array
+ * @param type The datatype of the array members
+ * @return Returns UA_STATUSCODE_GOOD or UA_STATUSCODE_BADOUTOFMEMORY. The
+ * original array is left untouched in the failure case. */
+UA_StatusCode UA_EXPORT
+UA_Array_resize(void **p, size_t *size, size_t newSize,
+ const UA_DataType *type) UA_FUNC_ATTR_WARN_UNUSED_RESULT;
+
+/* Append the given element at the end of the array. The content is moved
+ * (shallow copy) and the original memory is _init'ed if appending is
+ * successful.
+ *
+ * @param p Double pointer to the array memory. Can be overwritten by the result
+ * of a realloc.
+ * @param size The current size of the array. Overwritten in case of success.
+ * @param newElem The element to be appended. The memory is reset upon success.
+ * @param type The datatype of the array members
+ * @return Returns UA_STATUSCODE_GOOD or UA_STATUSCODE_BADOUTOFMEMORY. The
+ * original array is left untouched in the failure case. */
+UA_StatusCode UA_EXPORT
+UA_Array_append(void **p, size_t *size, void *newElem,
+ const UA_DataType *type) UA_FUNC_ATTR_WARN_UNUSED_RESULT;
+
+/* Append a copy of the given element at the end of the array.
+ *
+ * @param p Double pointer to the array memory. Can be overwritten by the result
+ * of a realloc.
+ * @param size The current size of the array. Overwritten in case of success.
+ * @param newElem The element to be appended.
+ * @param type The datatype of the array members
+ * @return Returns UA_STATUSCODE_GOOD or UA_STATUSCODE_BADOUTOFMEMORY. The
+ * original array is left untouched in the failure case. */
+
+UA_StatusCode UA_EXPORT
+UA_Array_appendCopy(void **p, size_t *size, const void *newElem,
+ const UA_DataType *type) UA_FUNC_ATTR_WARN_UNUSED_RESULT;
+
/* Deletes an array.
*
* @param p The memory location of the array
* @param size The size of the array
* @param type The datatype of the array members */
-void UA_EXPORT UA_Array_delete(void *p, size_t size, const UA_DataType *type);
+void UA_EXPORT
+UA_Array_delete(void *p, size_t size, const UA_DataType *type);
/**
* Random Number Generator
@@ -14088,27 +15004,17 @@ UA_Guid UA_EXPORT UA_Guid_random(void); /* no cryptographic entropy */
# define UA_TYPENAME(name)
#endif
-/* Datatype arrays with custom type definitions can be added in a linked list to
- * the client or server configuration. Datatype members can point to types in
- * the same array via the ``memberTypeIndex``. If ``namespaceZero`` is set to
- * true, the member datatype is looked up in the array of builtin datatypes
- * instead. */
-typedef struct UA_DataTypeArray {
- const struct UA_DataTypeArray *next;
- const size_t typesSize;
- const UA_DataType *types;
-} UA_DataTypeArray;
-
/**
* .. include:: types_generated.rst */
_UA_END_DECLS
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/build/src_generated/open62541/types_generated.h" ***********************************/
+/**** amalgamated original file "/build/src_generated/open62541/types_generated.h" ****/
-/* Generated from Opc.Ua.Types.bsd with script /home/pdie/sonstiges/qtopcua/repos/open62541/tools/generate_datatypes.py
- * on host mintaka by user pdie at 2021-06-21 11:34:37 */
+/**********************************
+ * Autogenerated -- do not modify *
+ **********************************/
#ifdef UA_ENABLE_AMALGAMATION
@@ -14116,6 +15022,8 @@ _UA_END_DECLS
#endif
+
+
_UA_BEGIN_DECLS
@@ -14123,7 +15031,7 @@ _UA_BEGIN_DECLS
* Every type is assigned an index in an array containing the type descriptions.
* These descriptions are used during type handling (copying, deletion,
* binary encoding, ...). */
-#define UA_TYPES_COUNT 208
+#define UA_TYPES_COUNT 211
extern UA_EXPORT const UA_DataType UA_TYPES[UA_TYPES_COUNT];
/**
@@ -14277,9 +15185,20 @@ extern UA_EXPORT const UA_DataType UA_TYPES[UA_TYPES_COUNT];
#define UA_TYPES_DIAGNOSTICINFO 24
/**
+ * KeyValuePair
+ * ^^^^^^^^^^^^
+ */
+typedef struct {
+ UA_QualifiedName key;
+ UA_Variant value;
+} UA_KeyValuePair;
+
+#define UA_TYPES_KEYVALUEPAIR 25
+
+/**
* NodeClass
* ^^^^^^^^^
- * A mask specifying the class of the node. */
+ */
typedef enum {
UA_NODECLASS_UNSPECIFIED = 0,
UA_NODECLASS_OBJECT = 1,
@@ -14294,7 +15213,7 @@ typedef enum {
} UA_NodeClass;
UA_STATIC_ASSERT(sizeof(UA_NodeClass) == sizeof(UA_Int32), enum_must_be_32bit);
-#define UA_TYPES_NODECLASS 25
+#define UA_TYPES_NODECLASS 26
/**
* StructureType
@@ -14308,7 +15227,7 @@ typedef enum {
} UA_StructureType;
UA_STATIC_ASSERT(sizeof(UA_StructureType) == sizeof(UA_Int32), enum_must_be_32bit);
-#define UA_TYPES_STRUCTURETYPE 26
+#define UA_TYPES_STRUCTURETYPE 27
/**
* StructureField
@@ -14325,7 +15244,7 @@ typedef struct {
UA_Boolean isOptional;
} UA_StructureField;
-#define UA_TYPES_STRUCTUREFIELD 27
+#define UA_TYPES_STRUCTUREFIELD 28
/**
* StructureDefinition
@@ -14339,12 +15258,12 @@ typedef struct {
UA_StructureField *fields;
} UA_StructureDefinition;
-#define UA_TYPES_STRUCTUREDEFINITION 28
+#define UA_TYPES_STRUCTUREDEFINITION 29
/**
* Argument
* ^^^^^^^^
- * An argument for a method. */
+ */
typedef struct {
UA_String name;
UA_NodeId dataType;
@@ -14354,19 +15273,19 @@ typedef struct {
UA_LocalizedText description;
} UA_Argument;
-#define UA_TYPES_ARGUMENT 29
+#define UA_TYPES_ARGUMENT 30
/**
* EnumValueType
* ^^^^^^^^^^^^^
- * A mapping between a value of an enumerated type and a name and description. */
+ */
typedef struct {
UA_Int64 value;
UA_LocalizedText displayName;
UA_LocalizedText description;
} UA_EnumValueType;
-#define UA_TYPES_ENUMVALUETYPE 30
+#define UA_TYPES_ENUMVALUETYPE 31
/**
* EnumField
@@ -14379,31 +15298,31 @@ typedef struct {
UA_String name;
} UA_EnumField;
-#define UA_TYPES_ENUMFIELD 31
+#define UA_TYPES_ENUMFIELD 32
/**
* Duration
* ^^^^^^^^
- * A period of time measured in milliseconds. */
+ */
typedef UA_Double UA_Duration;
-#define UA_TYPES_DURATION 32
+#define UA_TYPES_DURATION 33
/**
* UtcTime
* ^^^^^^^
- * A date/time value specified in Universal Coordinated Time (UTC). */
+ */
typedef UA_DateTime UA_UtcTime;
-#define UA_TYPES_UTCTIME 33
+#define UA_TYPES_UTCTIME 34
/**
* LocaleId
* ^^^^^^^^
- * An identifier for a user locale. */
+ */
typedef UA_String UA_LocaleId;
-#define UA_TYPES_LOCALEID 34
+#define UA_TYPES_LOCALEID 35
/**
* TimeZoneDataType
@@ -14414,12 +15333,12 @@ typedef struct {
UA_Boolean daylightSavingInOffset;
} UA_TimeZoneDataType;
-#define UA_TYPES_TIMEZONEDATATYPE 35
+#define UA_TYPES_TIMEZONEDATATYPE 36
/**
* ApplicationType
* ^^^^^^^^^^^^^^^
- * The types of applications. */
+ */
typedef enum {
UA_APPLICATIONTYPE_SERVER = 0,
UA_APPLICATIONTYPE_CLIENT = 1,
@@ -14429,12 +15348,12 @@ typedef enum {
} UA_ApplicationType;
UA_STATIC_ASSERT(sizeof(UA_ApplicationType) == sizeof(UA_Int32), enum_must_be_32bit);
-#define UA_TYPES_APPLICATIONTYPE 36
+#define UA_TYPES_APPLICATIONTYPE 37
/**
* ApplicationDescription
* ^^^^^^^^^^^^^^^^^^^^^^
- * Describes an application and how to find it. */
+ */
typedef struct {
UA_String applicationUri;
UA_String productUri;
@@ -14446,12 +15365,12 @@ typedef struct {
UA_String *discoveryUrls;
} UA_ApplicationDescription;
-#define UA_TYPES_APPLICATIONDESCRIPTION 37
+#define UA_TYPES_APPLICATIONDESCRIPTION 38
/**
* RequestHeader
* ^^^^^^^^^^^^^
- * The header passed with every server request. */
+ */
typedef struct {
UA_NodeId authenticationToken;
UA_DateTime timestamp;
@@ -14462,12 +15381,12 @@ typedef struct {
UA_ExtensionObject additionalHeader;
} UA_RequestHeader;
-#define UA_TYPES_REQUESTHEADER 38
+#define UA_TYPES_REQUESTHEADER 39
/**
* ResponseHeader
* ^^^^^^^^^^^^^^
- * The header passed with every server response. */
+ */
typedef struct {
UA_DateTime timestamp;
UA_UInt32 requestHandle;
@@ -14478,22 +15397,22 @@ typedef struct {
UA_ExtensionObject additionalHeader;
} UA_ResponseHeader;
-#define UA_TYPES_RESPONSEHEADER 39
+#define UA_TYPES_RESPONSEHEADER 40
/**
* ServiceFault
* ^^^^^^^^^^^^
- * The response returned by all services when there is a service level error. */
+ */
typedef struct {
UA_ResponseHeader responseHeader;
} UA_ServiceFault;
-#define UA_TYPES_SERVICEFAULT 40
+#define UA_TYPES_SERVICEFAULT 41
/**
* FindServersRequest
* ^^^^^^^^^^^^^^^^^^
- * Finds the servers known to the discovery server. */
+ */
typedef struct {
UA_RequestHeader requestHeader;
UA_String endpointUrl;
@@ -14503,24 +15422,24 @@ typedef struct {
UA_String *serverUris;
} UA_FindServersRequest;
-#define UA_TYPES_FINDSERVERSREQUEST 41
+#define UA_TYPES_FINDSERVERSREQUEST 42
/**
* FindServersResponse
* ^^^^^^^^^^^^^^^^^^^
- * Finds the servers known to the discovery server. */
+ */
typedef struct {
UA_ResponseHeader responseHeader;
size_t serversSize;
UA_ApplicationDescription *servers;
} UA_FindServersResponse;
-#define UA_TYPES_FINDSERVERSRESPONSE 42
+#define UA_TYPES_FINDSERVERSRESPONSE 43
/**
* MessageSecurityMode
* ^^^^^^^^^^^^^^^^^^^
- * The type of security to use on a message. */
+ */
typedef enum {
UA_MESSAGESECURITYMODE_INVALID = 0,
UA_MESSAGESECURITYMODE_NONE = 1,
@@ -14530,12 +15449,12 @@ typedef enum {
} UA_MessageSecurityMode;
UA_STATIC_ASSERT(sizeof(UA_MessageSecurityMode) == sizeof(UA_Int32), enum_must_be_32bit);
-#define UA_TYPES_MESSAGESECURITYMODE 43
+#define UA_TYPES_MESSAGESECURITYMODE 44
/**
* UserTokenType
* ^^^^^^^^^^^^^
- * The possible user token types. */
+ */
typedef enum {
UA_USERTOKENTYPE_ANONYMOUS = 0,
UA_USERTOKENTYPE_USERNAME = 1,
@@ -14545,12 +15464,12 @@ typedef enum {
} UA_UserTokenType;
UA_STATIC_ASSERT(sizeof(UA_UserTokenType) == sizeof(UA_Int32), enum_must_be_32bit);
-#define UA_TYPES_USERTOKENTYPE 44
+#define UA_TYPES_USERTOKENTYPE 45
/**
* UserTokenPolicy
* ^^^^^^^^^^^^^^^
- * Describes a user token that can be used with a server. */
+ */
typedef struct {
UA_String policyId;
UA_UserTokenType tokenType;
@@ -14559,12 +15478,12 @@ typedef struct {
UA_String securityPolicyUri;
} UA_UserTokenPolicy;
-#define UA_TYPES_USERTOKENPOLICY 45
+#define UA_TYPES_USERTOKENPOLICY 46
/**
* EndpointDescription
* ^^^^^^^^^^^^^^^^^^^
- * The description of a endpoint that can be used to access a server. */
+ */
typedef struct {
UA_String endpointUrl;
UA_ApplicationDescription server;
@@ -14577,12 +15496,12 @@ typedef struct {
UA_Byte securityLevel;
} UA_EndpointDescription;
-#define UA_TYPES_ENDPOINTDESCRIPTION 46
+#define UA_TYPES_ENDPOINTDESCRIPTION 47
/**
* GetEndpointsRequest
* ^^^^^^^^^^^^^^^^^^^
- * Gets the endpoints used by the server. */
+ */
typedef struct {
UA_RequestHeader requestHeader;
UA_String endpointUrl;
@@ -14592,24 +15511,24 @@ typedef struct {
UA_String *profileUris;
} UA_GetEndpointsRequest;
-#define UA_TYPES_GETENDPOINTSREQUEST 47
+#define UA_TYPES_GETENDPOINTSREQUEST 48
/**
* GetEndpointsResponse
* ^^^^^^^^^^^^^^^^^^^^
- * Gets the endpoints used by the server. */
+ */
typedef struct {
UA_ResponseHeader responseHeader;
size_t endpointsSize;
UA_EndpointDescription *endpoints;
} UA_GetEndpointsResponse;
-#define UA_TYPES_GETENDPOINTSRESPONSE 48
+#define UA_TYPES_GETENDPOINTSRESPONSE 49
/**
* SecurityTokenRequestType
* ^^^^^^^^^^^^^^^^^^^^^^^^
- * Indicates whether a token if being created or renewed. */
+ */
typedef enum {
UA_SECURITYTOKENREQUESTTYPE_ISSUE = 0,
UA_SECURITYTOKENREQUESTTYPE_RENEW = 1,
@@ -14617,12 +15536,12 @@ typedef enum {
} UA_SecurityTokenRequestType;
UA_STATIC_ASSERT(sizeof(UA_SecurityTokenRequestType) == sizeof(UA_Int32), enum_must_be_32bit);
-#define UA_TYPES_SECURITYTOKENREQUESTTYPE 49
+#define UA_TYPES_SECURITYTOKENREQUESTTYPE 50
/**
* ChannelSecurityToken
* ^^^^^^^^^^^^^^^^^^^^
- * The token that identifies a set of keys for an active secure channel. */
+ */
typedef struct {
UA_UInt32 channelId;
UA_UInt32 tokenId;
@@ -14630,12 +15549,12 @@ typedef struct {
UA_UInt32 revisedLifetime;
} UA_ChannelSecurityToken;
-#define UA_TYPES_CHANNELSECURITYTOKEN 50
+#define UA_TYPES_CHANNELSECURITYTOKEN 51
/**
* OpenSecureChannelRequest
* ^^^^^^^^^^^^^^^^^^^^^^^^
- * Creates a secure channel with a server. */
+ */
typedef struct {
UA_RequestHeader requestHeader;
UA_UInt32 clientProtocolVersion;
@@ -14645,12 +15564,12 @@ typedef struct {
UA_UInt32 requestedLifetime;
} UA_OpenSecureChannelRequest;
-#define UA_TYPES_OPENSECURECHANNELREQUEST 51
+#define UA_TYPES_OPENSECURECHANNELREQUEST 52
/**
* OpenSecureChannelResponse
* ^^^^^^^^^^^^^^^^^^^^^^^^^
- * Creates a secure channel with a server. */
+ */
typedef struct {
UA_ResponseHeader responseHeader;
UA_UInt32 serverProtocolVersion;
@@ -14658,54 +15577,54 @@ typedef struct {
UA_ByteString serverNonce;
} UA_OpenSecureChannelResponse;
-#define UA_TYPES_OPENSECURECHANNELRESPONSE 52
+#define UA_TYPES_OPENSECURECHANNELRESPONSE 53
/**
* CloseSecureChannelRequest
* ^^^^^^^^^^^^^^^^^^^^^^^^^
- * Closes a secure channel. */
+ */
typedef struct {
UA_RequestHeader requestHeader;
} UA_CloseSecureChannelRequest;
-#define UA_TYPES_CLOSESECURECHANNELREQUEST 53
+#define UA_TYPES_CLOSESECURECHANNELREQUEST 54
/**
* CloseSecureChannelResponse
* ^^^^^^^^^^^^^^^^^^^^^^^^^^
- * Closes a secure channel. */
+ */
typedef struct {
UA_ResponseHeader responseHeader;
} UA_CloseSecureChannelResponse;
-#define UA_TYPES_CLOSESECURECHANNELRESPONSE 54
+#define UA_TYPES_CLOSESECURECHANNELRESPONSE 55
/**
* SignedSoftwareCertificate
* ^^^^^^^^^^^^^^^^^^^^^^^^^
- * A software certificate with a digital signature. */
+ */
typedef struct {
UA_ByteString certificateData;
UA_ByteString signature;
} UA_SignedSoftwareCertificate;
-#define UA_TYPES_SIGNEDSOFTWARECERTIFICATE 55
+#define UA_TYPES_SIGNEDSOFTWARECERTIFICATE 56
/**
* SignatureData
* ^^^^^^^^^^^^^
- * A digital signature. */
+ */
typedef struct {
UA_String algorithm;
UA_ByteString signature;
} UA_SignatureData;
-#define UA_TYPES_SIGNATUREDATA 56
+#define UA_TYPES_SIGNATUREDATA 57
/**
* CreateSessionRequest
* ^^^^^^^^^^^^^^^^^^^^
- * Creates a new session with the server. */
+ */
typedef struct {
UA_RequestHeader requestHeader;
UA_ApplicationDescription clientDescription;
@@ -14718,12 +15637,12 @@ typedef struct {
UA_UInt32 maxResponseMessageSize;
} UA_CreateSessionRequest;
-#define UA_TYPES_CREATESESSIONREQUEST 57
+#define UA_TYPES_CREATESESSIONREQUEST 58
/**
* CreateSessionResponse
* ^^^^^^^^^^^^^^^^^^^^^
- * Creates a new session with the server. */
+ */
typedef struct {
UA_ResponseHeader responseHeader;
UA_NodeId sessionId;
@@ -14739,32 +15658,32 @@ typedef struct {
UA_UInt32 maxRequestMessageSize;
} UA_CreateSessionResponse;
-#define UA_TYPES_CREATESESSIONRESPONSE 58
+#define UA_TYPES_CREATESESSIONRESPONSE 59
/**
* UserIdentityToken
* ^^^^^^^^^^^^^^^^^
- * A base type for a user identity token. */
+ */
typedef struct {
UA_String policyId;
} UA_UserIdentityToken;
-#define UA_TYPES_USERIDENTITYTOKEN 59
+#define UA_TYPES_USERIDENTITYTOKEN 60
/**
* AnonymousIdentityToken
* ^^^^^^^^^^^^^^^^^^^^^^
- * A token representing an anonymous user. */
+ */
typedef struct {
UA_String policyId;
} UA_AnonymousIdentityToken;
-#define UA_TYPES_ANONYMOUSIDENTITYTOKEN 60
+#define UA_TYPES_ANONYMOUSIDENTITYTOKEN 61
/**
* UserNameIdentityToken
* ^^^^^^^^^^^^^^^^^^^^^
- * A token representing a user identified by a user name and password. */
+ */
typedef struct {
UA_String policyId;
UA_String userName;
@@ -14772,35 +15691,35 @@ typedef struct {
UA_String encryptionAlgorithm;
} UA_UserNameIdentityToken;
-#define UA_TYPES_USERNAMEIDENTITYTOKEN 61
+#define UA_TYPES_USERNAMEIDENTITYTOKEN 62
/**
* X509IdentityToken
* ^^^^^^^^^^^^^^^^^
- * A token representing a user identified by an X509 certificate. */
+ */
typedef struct {
UA_String policyId;
UA_ByteString certificateData;
} UA_X509IdentityToken;
-#define UA_TYPES_X509IDENTITYTOKEN 62
+#define UA_TYPES_X509IDENTITYTOKEN 63
/**
* IssuedIdentityToken
* ^^^^^^^^^^^^^^^^^^^
- * A token representing a user identified by a WS-Security XML token. */
+ */
typedef struct {
UA_String policyId;
UA_ByteString tokenData;
UA_String encryptionAlgorithm;
} UA_IssuedIdentityToken;
-#define UA_TYPES_ISSUEDIDENTITYTOKEN 63
+#define UA_TYPES_ISSUEDIDENTITYTOKEN 64
/**
* ActivateSessionRequest
* ^^^^^^^^^^^^^^^^^^^^^^
- * Activates a session with the server. */
+ */
typedef struct {
UA_RequestHeader requestHeader;
UA_SignatureData clientSignature;
@@ -14812,12 +15731,12 @@ typedef struct {
UA_SignatureData userTokenSignature;
} UA_ActivateSessionRequest;
-#define UA_TYPES_ACTIVATESESSIONREQUEST 64
+#define UA_TYPES_ACTIVATESESSIONREQUEST 65
/**
* ActivateSessionResponse
* ^^^^^^^^^^^^^^^^^^^^^^^
- * Activates a session with the server. */
+ */
typedef struct {
UA_ResponseHeader responseHeader;
UA_ByteString serverNonce;
@@ -14827,33 +15746,33 @@ typedef struct {
UA_DiagnosticInfo *diagnosticInfos;
} UA_ActivateSessionResponse;
-#define UA_TYPES_ACTIVATESESSIONRESPONSE 65
+#define UA_TYPES_ACTIVATESESSIONRESPONSE 66
/**
* CloseSessionRequest
* ^^^^^^^^^^^^^^^^^^^
- * Closes a session with the server. */
+ */
typedef struct {
UA_RequestHeader requestHeader;
UA_Boolean deleteSubscriptions;
} UA_CloseSessionRequest;
-#define UA_TYPES_CLOSESESSIONREQUEST 66
+#define UA_TYPES_CLOSESESSIONREQUEST 67
/**
* CloseSessionResponse
* ^^^^^^^^^^^^^^^^^^^^
- * Closes a session with the server. */
+ */
typedef struct {
UA_ResponseHeader responseHeader;
} UA_CloseSessionResponse;
-#define UA_TYPES_CLOSESESSIONRESPONSE 67
+#define UA_TYPES_CLOSESESSIONRESPONSE 68
/**
* NodeAttributesMask
* ^^^^^^^^^^^^^^^^^^
- * The bits used to specify default attributes for a new node. */
+ */
typedef enum {
UA_NODEATTRIBUTESMASK_NONE = 0,
UA_NODEATTRIBUTESMASK_ACCESSLEVEL = 1,
@@ -14894,12 +15813,12 @@ typedef enum {
} UA_NodeAttributesMask;
UA_STATIC_ASSERT(sizeof(UA_NodeAttributesMask) == sizeof(UA_Int32), enum_must_be_32bit);
-#define UA_TYPES_NODEATTRIBUTESMASK 68
+#define UA_TYPES_NODEATTRIBUTESMASK 69
/**
* NodeAttributes
* ^^^^^^^^^^^^^^
- * The base attributes for all nodes. */
+ */
typedef struct {
UA_UInt32 specifiedAttributes;
UA_LocalizedText displayName;
@@ -14908,12 +15827,12 @@ typedef struct {
UA_UInt32 userWriteMask;
} UA_NodeAttributes;
-#define UA_TYPES_NODEATTRIBUTES 69
+#define UA_TYPES_NODEATTRIBUTES 70
/**
* ObjectAttributes
* ^^^^^^^^^^^^^^^^
- * The attributes for an object node. */
+ */
typedef struct {
UA_UInt32 specifiedAttributes;
UA_LocalizedText displayName;
@@ -14923,12 +15842,12 @@ typedef struct {
UA_Byte eventNotifier;
} UA_ObjectAttributes;
-#define UA_TYPES_OBJECTATTRIBUTES 70
+#define UA_TYPES_OBJECTATTRIBUTES 71
/**
* VariableAttributes
* ^^^^^^^^^^^^^^^^^^
- * The attributes for a variable node. */
+ */
typedef struct {
UA_UInt32 specifiedAttributes;
UA_LocalizedText displayName;
@@ -14946,12 +15865,12 @@ typedef struct {
UA_Boolean historizing;
} UA_VariableAttributes;
-#define UA_TYPES_VARIABLEATTRIBUTES 71
+#define UA_TYPES_VARIABLEATTRIBUTES 72
/**
* MethodAttributes
* ^^^^^^^^^^^^^^^^
- * The attributes for a method node. */
+ */
typedef struct {
UA_UInt32 specifiedAttributes;
UA_LocalizedText displayName;
@@ -14962,12 +15881,12 @@ typedef struct {
UA_Boolean userExecutable;
} UA_MethodAttributes;
-#define UA_TYPES_METHODATTRIBUTES 72
+#define UA_TYPES_METHODATTRIBUTES 73
/**
* ObjectTypeAttributes
* ^^^^^^^^^^^^^^^^^^^^
- * The attributes for an object type node. */
+ */
typedef struct {
UA_UInt32 specifiedAttributes;
UA_LocalizedText displayName;
@@ -14977,12 +15896,12 @@ typedef struct {
UA_Boolean isAbstract;
} UA_ObjectTypeAttributes;
-#define UA_TYPES_OBJECTTYPEATTRIBUTES 73
+#define UA_TYPES_OBJECTTYPEATTRIBUTES 74
/**
* VariableTypeAttributes
* ^^^^^^^^^^^^^^^^^^^^^^
- * The attributes for a variable type node. */
+ */
typedef struct {
UA_UInt32 specifiedAttributes;
UA_LocalizedText displayName;
@@ -14997,12 +15916,12 @@ typedef struct {
UA_Boolean isAbstract;
} UA_VariableTypeAttributes;
-#define UA_TYPES_VARIABLETYPEATTRIBUTES 74
+#define UA_TYPES_VARIABLETYPEATTRIBUTES 75
/**
* ReferenceTypeAttributes
* ^^^^^^^^^^^^^^^^^^^^^^^
- * The attributes for a reference type node. */
+ */
typedef struct {
UA_UInt32 specifiedAttributes;
UA_LocalizedText displayName;
@@ -15014,12 +15933,12 @@ typedef struct {
UA_LocalizedText inverseName;
} UA_ReferenceTypeAttributes;
-#define UA_TYPES_REFERENCETYPEATTRIBUTES 75
+#define UA_TYPES_REFERENCETYPEATTRIBUTES 76
/**
* DataTypeAttributes
* ^^^^^^^^^^^^^^^^^^
- * The attributes for a data type node. */
+ */
typedef struct {
UA_UInt32 specifiedAttributes;
UA_LocalizedText displayName;
@@ -15029,12 +15948,12 @@ typedef struct {
UA_Boolean isAbstract;
} UA_DataTypeAttributes;
-#define UA_TYPES_DATATYPEATTRIBUTES 76
+#define UA_TYPES_DATATYPEATTRIBUTES 77
/**
* ViewAttributes
* ^^^^^^^^^^^^^^
- * The attributes for a view node. */
+ */
typedef struct {
UA_UInt32 specifiedAttributes;
UA_LocalizedText displayName;
@@ -15045,12 +15964,12 @@ typedef struct {
UA_Byte eventNotifier;
} UA_ViewAttributes;
-#define UA_TYPES_VIEWATTRIBUTES 77
+#define UA_TYPES_VIEWATTRIBUTES 78
/**
* AddNodesItem
* ^^^^^^^^^^^^
- * A request to add a node to the server address space. */
+ */
typedef struct {
UA_ExpandedNodeId parentNodeId;
UA_NodeId referenceTypeId;
@@ -15061,35 +15980,35 @@ typedef struct {
UA_ExpandedNodeId typeDefinition;
} UA_AddNodesItem;
-#define UA_TYPES_ADDNODESITEM 78
+#define UA_TYPES_ADDNODESITEM 79
/**
* AddNodesResult
* ^^^^^^^^^^^^^^
- * A result of an add node operation. */
+ */
typedef struct {
UA_StatusCode statusCode;
UA_NodeId addedNodeId;
} UA_AddNodesResult;
-#define UA_TYPES_ADDNODESRESULT 79
+#define UA_TYPES_ADDNODESRESULT 80
/**
* AddNodesRequest
* ^^^^^^^^^^^^^^^
- * Adds one or more nodes to the server address space. */
+ */
typedef struct {
UA_RequestHeader requestHeader;
size_t nodesToAddSize;
UA_AddNodesItem *nodesToAdd;
} UA_AddNodesRequest;
-#define UA_TYPES_ADDNODESREQUEST 80
+#define UA_TYPES_ADDNODESREQUEST 81
/**
* AddNodesResponse
* ^^^^^^^^^^^^^^^^
- * Adds one or more nodes to the server address space. */
+ */
typedef struct {
UA_ResponseHeader responseHeader;
size_t resultsSize;
@@ -15098,12 +16017,12 @@ typedef struct {
UA_DiagnosticInfo *diagnosticInfos;
} UA_AddNodesResponse;
-#define UA_TYPES_ADDNODESRESPONSE 81
+#define UA_TYPES_ADDNODESRESPONSE 82
/**
* AddReferencesItem
* ^^^^^^^^^^^^^^^^^
- * A request to add a reference to the server address space. */
+ */
typedef struct {
UA_NodeId sourceNodeId;
UA_NodeId referenceTypeId;
@@ -15113,24 +16032,24 @@ typedef struct {
UA_NodeClass targetNodeClass;
} UA_AddReferencesItem;
-#define UA_TYPES_ADDREFERENCESITEM 82
+#define UA_TYPES_ADDREFERENCESITEM 83
/**
* AddReferencesRequest
* ^^^^^^^^^^^^^^^^^^^^
- * Adds one or more references to the server address space. */
+ */
typedef struct {
UA_RequestHeader requestHeader;
size_t referencesToAddSize;
UA_AddReferencesItem *referencesToAdd;
} UA_AddReferencesRequest;
-#define UA_TYPES_ADDREFERENCESREQUEST 83
+#define UA_TYPES_ADDREFERENCESREQUEST 84
/**
* AddReferencesResponse
* ^^^^^^^^^^^^^^^^^^^^^
- * Adds one or more references to the server address space. */
+ */
typedef struct {
UA_ResponseHeader responseHeader;
size_t resultsSize;
@@ -15139,35 +16058,35 @@ typedef struct {
UA_DiagnosticInfo *diagnosticInfos;
} UA_AddReferencesResponse;
-#define UA_TYPES_ADDREFERENCESRESPONSE 84
+#define UA_TYPES_ADDREFERENCESRESPONSE 85
/**
* DeleteNodesItem
* ^^^^^^^^^^^^^^^
- * A request to delete a node to the server address space. */
+ */
typedef struct {
UA_NodeId nodeId;
UA_Boolean deleteTargetReferences;
} UA_DeleteNodesItem;
-#define UA_TYPES_DELETENODESITEM 85
+#define UA_TYPES_DELETENODESITEM 86
/**
* DeleteNodesRequest
* ^^^^^^^^^^^^^^^^^^
- * Delete one or more nodes from the server address space. */
+ */
typedef struct {
UA_RequestHeader requestHeader;
size_t nodesToDeleteSize;
UA_DeleteNodesItem *nodesToDelete;
} UA_DeleteNodesRequest;
-#define UA_TYPES_DELETENODESREQUEST 86
+#define UA_TYPES_DELETENODESREQUEST 87
/**
* DeleteNodesResponse
* ^^^^^^^^^^^^^^^^^^^
- * Delete one or more nodes from the server address space. */
+ */
typedef struct {
UA_ResponseHeader responseHeader;
size_t resultsSize;
@@ -15176,12 +16095,12 @@ typedef struct {
UA_DiagnosticInfo *diagnosticInfos;
} UA_DeleteNodesResponse;
-#define UA_TYPES_DELETENODESRESPONSE 87
+#define UA_TYPES_DELETENODESRESPONSE 88
/**
* DeleteReferencesItem
* ^^^^^^^^^^^^^^^^^^^^
- * A request to delete a node from the server address space. */
+ */
typedef struct {
UA_NodeId sourceNodeId;
UA_NodeId referenceTypeId;
@@ -15190,24 +16109,24 @@ typedef struct {
UA_Boolean deleteBidirectional;
} UA_DeleteReferencesItem;
-#define UA_TYPES_DELETEREFERENCESITEM 88
+#define UA_TYPES_DELETEREFERENCESITEM 89
/**
* DeleteReferencesRequest
* ^^^^^^^^^^^^^^^^^^^^^^^
- * Delete one or more references from the server address space. */
+ */
typedef struct {
UA_RequestHeader requestHeader;
size_t referencesToDeleteSize;
UA_DeleteReferencesItem *referencesToDelete;
} UA_DeleteReferencesRequest;
-#define UA_TYPES_DELETEREFERENCESREQUEST 89
+#define UA_TYPES_DELETEREFERENCESREQUEST 90
/**
* DeleteReferencesResponse
* ^^^^^^^^^^^^^^^^^^^^^^^^
- * Delete one or more references from the server address space. */
+ */
typedef struct {
UA_ResponseHeader responseHeader;
size_t resultsSize;
@@ -15216,12 +16135,12 @@ typedef struct {
UA_DiagnosticInfo *diagnosticInfos;
} UA_DeleteReferencesResponse;
-#define UA_TYPES_DELETEREFERENCESRESPONSE 90
+#define UA_TYPES_DELETEREFERENCESRESPONSE 91
/**
* BrowseDirection
* ^^^^^^^^^^^^^^^
- * The directions of the references to return. */
+ */
typedef enum {
UA_BROWSEDIRECTION_FORWARD = 0,
UA_BROWSEDIRECTION_INVERSE = 1,
@@ -15231,24 +16150,24 @@ typedef enum {
} UA_BrowseDirection;
UA_STATIC_ASSERT(sizeof(UA_BrowseDirection) == sizeof(UA_Int32), enum_must_be_32bit);
-#define UA_TYPES_BROWSEDIRECTION 91
+#define UA_TYPES_BROWSEDIRECTION 92
/**
* ViewDescription
* ^^^^^^^^^^^^^^^
- * The view to browse. */
+ */
typedef struct {
UA_NodeId viewId;
UA_DateTime timestamp;
UA_UInt32 viewVersion;
} UA_ViewDescription;
-#define UA_TYPES_VIEWDESCRIPTION 92
+#define UA_TYPES_VIEWDESCRIPTION 93
/**
* BrowseDescription
* ^^^^^^^^^^^^^^^^^
- * A request to browse the the references from a node. */
+ */
typedef struct {
UA_NodeId nodeId;
UA_BrowseDirection browseDirection;
@@ -15258,12 +16177,12 @@ typedef struct {
UA_UInt32 resultMask;
} UA_BrowseDescription;
-#define UA_TYPES_BROWSEDESCRIPTION 93
+#define UA_TYPES_BROWSEDESCRIPTION 94
/**
* BrowseResultMask
* ^^^^^^^^^^^^^^^^
- * A bit mask which specifies what should be returned in a browse response. */
+ */
typedef enum {
UA_BROWSERESULTMASK_NONE = 0,
UA_BROWSERESULTMASK_REFERENCETYPEID = 1,
@@ -15279,12 +16198,12 @@ typedef enum {
} UA_BrowseResultMask;
UA_STATIC_ASSERT(sizeof(UA_BrowseResultMask) == sizeof(UA_Int32), enum_must_be_32bit);
-#define UA_TYPES_BROWSERESULTMASK 94
+#define UA_TYPES_BROWSERESULTMASK 95
/**
* ReferenceDescription
* ^^^^^^^^^^^^^^^^^^^^
- * The description of a reference. */
+ */
typedef struct {
UA_NodeId referenceTypeId;
UA_Boolean isForward;
@@ -15295,12 +16214,12 @@ typedef struct {
UA_ExpandedNodeId typeDefinition;
} UA_ReferenceDescription;
-#define UA_TYPES_REFERENCEDESCRIPTION 95
+#define UA_TYPES_REFERENCEDESCRIPTION 96
/**
* BrowseResult
* ^^^^^^^^^^^^
- * The result of a browse operation. */
+ */
typedef struct {
UA_StatusCode statusCode;
UA_ByteString continuationPoint;
@@ -15308,12 +16227,12 @@ typedef struct {
UA_ReferenceDescription *references;
} UA_BrowseResult;
-#define UA_TYPES_BROWSERESULT 96
+#define UA_TYPES_BROWSERESULT 97
/**
* BrowseRequest
* ^^^^^^^^^^^^^
- * Browse the references for one or more nodes from the server address space. */
+ */
typedef struct {
UA_RequestHeader requestHeader;
UA_ViewDescription view;
@@ -15322,12 +16241,12 @@ typedef struct {
UA_BrowseDescription *nodesToBrowse;
} UA_BrowseRequest;
-#define UA_TYPES_BROWSEREQUEST 97
+#define UA_TYPES_BROWSEREQUEST 98
/**
* BrowseResponse
* ^^^^^^^^^^^^^^
- * Browse the references for one or more nodes from the server address space. */
+ */
typedef struct {
UA_ResponseHeader responseHeader;
size_t resultsSize;
@@ -15336,12 +16255,12 @@ typedef struct {
UA_DiagnosticInfo *diagnosticInfos;
} UA_BrowseResponse;
-#define UA_TYPES_BROWSERESPONSE 98
+#define UA_TYPES_BROWSERESPONSE 99
/**
* BrowseNextRequest
* ^^^^^^^^^^^^^^^^^
- * Continues one or more browse operations. */
+ */
typedef struct {
UA_RequestHeader requestHeader;
UA_Boolean releaseContinuationPoints;
@@ -15349,12 +16268,12 @@ typedef struct {
UA_ByteString *continuationPoints;
} UA_BrowseNextRequest;
-#define UA_TYPES_BROWSENEXTREQUEST 99
+#define UA_TYPES_BROWSENEXTREQUEST 100
/**
* BrowseNextResponse
* ^^^^^^^^^^^^^^^^^^
- * Continues one or more browse operations. */
+ */
typedef struct {
UA_ResponseHeader responseHeader;
size_t resultsSize;
@@ -15363,12 +16282,12 @@ typedef struct {
UA_DiagnosticInfo *diagnosticInfos;
} UA_BrowseNextResponse;
-#define UA_TYPES_BROWSENEXTRESPONSE 100
+#define UA_TYPES_BROWSENEXTRESPONSE 101
/**
* RelativePathElement
* ^^^^^^^^^^^^^^^^^^^
- * An element in a relative path. */
+ */
typedef struct {
UA_NodeId referenceTypeId;
UA_Boolean isInverse;
@@ -15376,69 +16295,69 @@ typedef struct {
UA_QualifiedName targetName;
} UA_RelativePathElement;
-#define UA_TYPES_RELATIVEPATHELEMENT 101
+#define UA_TYPES_RELATIVEPATHELEMENT 102
/**
* RelativePath
* ^^^^^^^^^^^^
- * A relative path constructed from reference types and browse names. */
+ */
typedef struct {
size_t elementsSize;
UA_RelativePathElement *elements;
} UA_RelativePath;
-#define UA_TYPES_RELATIVEPATH 102
+#define UA_TYPES_RELATIVEPATH 103
/**
* BrowsePath
* ^^^^^^^^^^
- * A request to translate a path into a node id. */
+ */
typedef struct {
UA_NodeId startingNode;
UA_RelativePath relativePath;
} UA_BrowsePath;
-#define UA_TYPES_BROWSEPATH 103
+#define UA_TYPES_BROWSEPATH 104
/**
* BrowsePathTarget
* ^^^^^^^^^^^^^^^^
- * The target of the translated path. */
+ */
typedef struct {
UA_ExpandedNodeId targetId;
UA_UInt32 remainingPathIndex;
} UA_BrowsePathTarget;
-#define UA_TYPES_BROWSEPATHTARGET 104
+#define UA_TYPES_BROWSEPATHTARGET 105
/**
* BrowsePathResult
* ^^^^^^^^^^^^^^^^
- * The result of a translate opearation. */
+ */
typedef struct {
UA_StatusCode statusCode;
size_t targetsSize;
UA_BrowsePathTarget *targets;
} UA_BrowsePathResult;
-#define UA_TYPES_BROWSEPATHRESULT 105
+#define UA_TYPES_BROWSEPATHRESULT 106
/**
* TranslateBrowsePathsToNodeIdsRequest
* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- * Translates one or more paths in the server address space. */
+ */
typedef struct {
UA_RequestHeader requestHeader;
size_t browsePathsSize;
UA_BrowsePath *browsePaths;
} UA_TranslateBrowsePathsToNodeIdsRequest;
-#define UA_TYPES_TRANSLATEBROWSEPATHSTONODEIDSREQUEST 106
+#define UA_TYPES_TRANSLATEBROWSEPATHSTONODEIDSREQUEST 107
/**
* TranslateBrowsePathsToNodeIdsResponse
* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- * Translates one or more paths in the server address space. */
+ */
typedef struct {
UA_ResponseHeader responseHeader;
size_t resultsSize;
@@ -15447,53 +16366,53 @@ typedef struct {
UA_DiagnosticInfo *diagnosticInfos;
} UA_TranslateBrowsePathsToNodeIdsResponse;
-#define UA_TYPES_TRANSLATEBROWSEPATHSTONODEIDSRESPONSE 107
+#define UA_TYPES_TRANSLATEBROWSEPATHSTONODEIDSRESPONSE 108
/**
* RegisterNodesRequest
* ^^^^^^^^^^^^^^^^^^^^
- * Registers one or more nodes for repeated use within a session. */
+ */
typedef struct {
UA_RequestHeader requestHeader;
size_t nodesToRegisterSize;
UA_NodeId *nodesToRegister;
} UA_RegisterNodesRequest;
-#define UA_TYPES_REGISTERNODESREQUEST 108
+#define UA_TYPES_REGISTERNODESREQUEST 109
/**
* RegisterNodesResponse
* ^^^^^^^^^^^^^^^^^^^^^
- * Registers one or more nodes for repeated use within a session. */
+ */
typedef struct {
UA_ResponseHeader responseHeader;
size_t registeredNodeIdsSize;
UA_NodeId *registeredNodeIds;
} UA_RegisterNodesResponse;
-#define UA_TYPES_REGISTERNODESRESPONSE 109
+#define UA_TYPES_REGISTERNODESRESPONSE 110
/**
* UnregisterNodesRequest
* ^^^^^^^^^^^^^^^^^^^^^^
- * Unregisters one or more previously registered nodes. */
+ */
typedef struct {
UA_RequestHeader requestHeader;
size_t nodesToUnregisterSize;
UA_NodeId *nodesToUnregister;
} UA_UnregisterNodesRequest;
-#define UA_TYPES_UNREGISTERNODESREQUEST 110
+#define UA_TYPES_UNREGISTERNODESREQUEST 111
/**
* UnregisterNodesResponse
* ^^^^^^^^^^^^^^^^^^^^^^^
- * Unregisters one or more previously registered nodes. */
+ */
typedef struct {
UA_ResponseHeader responseHeader;
} UA_UnregisterNodesResponse;
-#define UA_TYPES_UNREGISTERNODESRESPONSE 111
+#define UA_TYPES_UNREGISTERNODESRESPONSE 112
/**
* FilterOperator
@@ -15522,7 +16441,7 @@ typedef enum {
} UA_FilterOperator;
UA_STATIC_ASSERT(sizeof(UA_FilterOperator) == sizeof(UA_Int32), enum_must_be_32bit);
-#define UA_TYPES_FILTEROPERATOR 112
+#define UA_TYPES_FILTEROPERATOR 113
/**
* ContentFilterElement
@@ -15534,7 +16453,7 @@ typedef struct {
UA_ExtensionObject *filterOperands;
} UA_ContentFilterElement;
-#define UA_TYPES_CONTENTFILTERELEMENT 113
+#define UA_TYPES_CONTENTFILTERELEMENT 114
/**
* ContentFilter
@@ -15545,15 +16464,7 @@ typedef struct {
UA_ContentFilterElement *elements;
} UA_ContentFilter;
-#define UA_TYPES_CONTENTFILTER 114
-
-/**
- * FilterOperand
- * ^^^^^^^^^^^^^
- */
-typedef void * UA_FilterOperand;
-
-#define UA_TYPES_FILTEROPERAND 115
+#define UA_TYPES_CONTENTFILTER 115
/**
* ElementOperand
@@ -16494,6 +17405,45 @@ typedef struct {
#define UA_TYPES_REPUBLISHRESPONSE 185
/**
+ * TransferResult
+ * ^^^^^^^^^^^^^^
+ */
+typedef struct {
+ UA_StatusCode statusCode;
+ size_t availableSequenceNumbersSize;
+ UA_UInt32 *availableSequenceNumbers;
+} UA_TransferResult;
+
+#define UA_TYPES_TRANSFERRESULT 186
+
+/**
+ * TransferSubscriptionsRequest
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ */
+typedef struct {
+ UA_RequestHeader requestHeader;
+ size_t subscriptionIdsSize;
+ UA_UInt32 *subscriptionIds;
+ UA_Boolean sendInitialValues;
+} UA_TransferSubscriptionsRequest;
+
+#define UA_TYPES_TRANSFERSUBSCRIPTIONSREQUEST 187
+
+/**
+ * TransferSubscriptionsResponse
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ */
+typedef struct {
+ UA_ResponseHeader responseHeader;
+ size_t resultsSize;
+ UA_TransferResult *results;
+ size_t diagnosticInfosSize;
+ UA_DiagnosticInfo *diagnosticInfos;
+} UA_TransferSubscriptionsResponse;
+
+#define UA_TYPES_TRANSFERSUBSCRIPTIONSRESPONSE 188
+
+/**
* DeleteSubscriptionsRequest
* ^^^^^^^^^^^^^^^^^^^^^^^^^^
*/
@@ -16503,7 +17453,7 @@ typedef struct {
UA_UInt32 *subscriptionIds;
} UA_DeleteSubscriptionsRequest;
-#define UA_TYPES_DELETESUBSCRIPTIONSREQUEST 186
+#define UA_TYPES_DELETESUBSCRIPTIONSREQUEST 189
/**
* DeleteSubscriptionsResponse
@@ -16517,7 +17467,7 @@ typedef struct {
UA_DiagnosticInfo *diagnosticInfos;
} UA_DeleteSubscriptionsResponse;
-#define UA_TYPES_DELETESUBSCRIPTIONSRESPONSE 187
+#define UA_TYPES_DELETESUBSCRIPTIONSRESPONSE 190
/**
* BuildInfo
@@ -16532,7 +17482,7 @@ typedef struct {
UA_DateTime buildDate;
} UA_BuildInfo;
-#define UA_TYPES_BUILDINFO 188
+#define UA_TYPES_BUILDINFO 191
/**
* RedundancySupport
@@ -16549,7 +17499,7 @@ typedef enum {
} UA_RedundancySupport;
UA_STATIC_ASSERT(sizeof(UA_RedundancySupport) == sizeof(UA_Int32), enum_must_be_32bit);
-#define UA_TYPES_REDUNDANCYSUPPORT 189
+#define UA_TYPES_REDUNDANCYSUPPORT 192
/**
* ServerState
@@ -16568,7 +17518,7 @@ typedef enum {
} UA_ServerState;
UA_STATIC_ASSERT(sizeof(UA_ServerState) == sizeof(UA_Int32), enum_must_be_32bit);
-#define UA_TYPES_SERVERSTATE 190
+#define UA_TYPES_SERVERSTATE 193
/**
* ServerDiagnosticsSummaryDataType
@@ -16589,7 +17539,7 @@ typedef struct {
UA_UInt32 rejectedRequestsCount;
} UA_ServerDiagnosticsSummaryDataType;
-#define UA_TYPES_SERVERDIAGNOSTICSSUMMARYDATATYPE 191
+#define UA_TYPES_SERVERDIAGNOSTICSSUMMARYDATATYPE 194
/**
* ServerStatusDataType
@@ -16604,7 +17554,7 @@ typedef struct {
UA_LocalizedText shutdownReason;
} UA_ServerStatusDataType;
-#define UA_TYPES_SERVERSTATUSDATATYPE 192
+#define UA_TYPES_SERVERSTATUSDATATYPE 195
/**
* Range
@@ -16615,7 +17565,7 @@ typedef struct {
UA_Double high;
} UA_Range;
-#define UA_TYPES_RANGE 193
+#define UA_TYPES_RANGE 196
/**
* EUInformation
@@ -16628,7 +17578,7 @@ typedef struct {
UA_LocalizedText description;
} UA_EUInformation;
-#define UA_TYPES_EUINFORMATION 194
+#define UA_TYPES_EUINFORMATION 197
/**
* AxisScaleEnumeration
@@ -16642,7 +17592,7 @@ typedef enum {
} UA_AxisScaleEnumeration;
UA_STATIC_ASSERT(sizeof(UA_AxisScaleEnumeration) == sizeof(UA_Int32), enum_must_be_32bit);
-#define UA_TYPES_AXISSCALEENUMERATION 195
+#define UA_TYPES_AXISSCALEENUMERATION 198
/**
* ComplexNumberType
@@ -16653,7 +17603,7 @@ typedef struct {
UA_Float imaginary;
} UA_ComplexNumberType;
-#define UA_TYPES_COMPLEXNUMBERTYPE 196
+#define UA_TYPES_COMPLEXNUMBERTYPE 199
/**
* DoubleComplexNumberType
@@ -16664,7 +17614,7 @@ typedef struct {
UA_Double imaginary;
} UA_DoubleComplexNumberType;
-#define UA_TYPES_DOUBLECOMPLEXNUMBERTYPE 197
+#define UA_TYPES_DOUBLECOMPLEXNUMBERTYPE 200
/**
* AxisInformation
@@ -16679,7 +17629,7 @@ typedef struct {
UA_Double *axisSteps;
} UA_AxisInformation;
-#define UA_TYPES_AXISINFORMATION 198
+#define UA_TYPES_AXISINFORMATION 201
/**
* XVType
@@ -16690,7 +17640,7 @@ typedef struct {
UA_Float value;
} UA_XVType;
-#define UA_TYPES_XVTYPE 199
+#define UA_TYPES_XVTYPE 202
/**
* EnumDefinition
@@ -16701,7 +17651,7 @@ typedef struct {
UA_EnumField *fields;
} UA_EnumDefinition;
-#define UA_TYPES_ENUMDEFINITION 200
+#define UA_TYPES_ENUMDEFINITION 203
/**
* ReadEventDetails
@@ -16714,7 +17664,7 @@ typedef struct {
UA_EventFilter filter;
} UA_ReadEventDetails;
-#define UA_TYPES_READEVENTDETAILS 201
+#define UA_TYPES_READEVENTDETAILS 204
/**
* ReadProcessedDetails
@@ -16729,7 +17679,7 @@ typedef struct {
UA_AggregateConfiguration aggregateConfiguration;
} UA_ReadProcessedDetails;
-#define UA_TYPES_READPROCESSEDDETAILS 202
+#define UA_TYPES_READPROCESSEDDETAILS 205
/**
* ModificationInfo
@@ -16741,7 +17691,7 @@ typedef struct {
UA_String userName;
} UA_ModificationInfo;
-#define UA_TYPES_MODIFICATIONINFO 203
+#define UA_TYPES_MODIFICATIONINFO 206
/**
* HistoryModifiedData
@@ -16754,7 +17704,7 @@ typedef struct {
UA_ModificationInfo *modificationInfos;
} UA_HistoryModifiedData;
-#define UA_TYPES_HISTORYMODIFIEDDATA 204
+#define UA_TYPES_HISTORYMODIFIEDDATA 207
/**
* HistoryEvent
@@ -16765,7 +17715,7 @@ typedef struct {
UA_HistoryEventFieldList *events;
} UA_HistoryEvent;
-#define UA_TYPES_HISTORYEVENT 205
+#define UA_TYPES_HISTORYEVENT 208
/**
* DataChangeNotification
@@ -16778,7 +17728,7 @@ typedef struct {
UA_DiagnosticInfo *diagnosticInfos;
} UA_DataChangeNotification;
-#define UA_TYPES_DATACHANGENOTIFICATION 206
+#define UA_TYPES_DATACHANGENOTIFICATION 209
/**
* EventNotificationList
@@ -16789,16 +17739,17 @@ typedef struct {
UA_EventFieldList *events;
} UA_EventNotificationList;
-#define UA_TYPES_EVENTNOTIFICATIONLIST 207
+#define UA_TYPES_EVENTNOTIFICATIONLIST 210
_UA_END_DECLS
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/build/src_generated/open62541/types_generated_handling.h" ***********************************/
+/**** amalgamated original file "/build/src_generated/open62541/types_generated_handling.h" ****/
-/* Generated from Opc.Ua.Types.bsd with script /home/pdie/sonstiges/qtopcua/repos/open62541/tools/generate_datatypes.py
- * on host mintaka by user pdie at 2021-06-21 11:34:37 */
+/**********************************
+ * Autogenerated -- do not modify *
+ **********************************/
@@ -16827,7 +17778,7 @@ UA_Boolean_copy(const UA_Boolean *src, UA_Boolean *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_BOOLEAN]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_Boolean_deleteMembers(UA_Boolean *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_BOOLEAN]);
}
@@ -16858,7 +17809,7 @@ UA_SByte_copy(const UA_SByte *src, UA_SByte *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_SBYTE]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_SByte_deleteMembers(UA_SByte *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_SBYTE]);
}
@@ -16889,7 +17840,7 @@ UA_Byte_copy(const UA_Byte *src, UA_Byte *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_BYTE]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_Byte_deleteMembers(UA_Byte *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_BYTE]);
}
@@ -16920,7 +17871,7 @@ UA_Int16_copy(const UA_Int16 *src, UA_Int16 *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_INT16]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_Int16_deleteMembers(UA_Int16 *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_INT16]);
}
@@ -16951,7 +17902,7 @@ UA_UInt16_copy(const UA_UInt16 *src, UA_UInt16 *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_UINT16]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_UInt16_deleteMembers(UA_UInt16 *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_UINT16]);
}
@@ -16982,7 +17933,7 @@ UA_Int32_copy(const UA_Int32 *src, UA_Int32 *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_INT32]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_Int32_deleteMembers(UA_Int32 *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_INT32]);
}
@@ -17013,7 +17964,7 @@ UA_UInt32_copy(const UA_UInt32 *src, UA_UInt32 *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_UINT32]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_UInt32_deleteMembers(UA_UInt32 *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_UINT32]);
}
@@ -17044,7 +17995,7 @@ UA_Int64_copy(const UA_Int64 *src, UA_Int64 *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_INT64]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_Int64_deleteMembers(UA_Int64 *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_INT64]);
}
@@ -17075,7 +18026,7 @@ UA_UInt64_copy(const UA_UInt64 *src, UA_UInt64 *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_UINT64]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_UInt64_deleteMembers(UA_UInt64 *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_UINT64]);
}
@@ -17106,7 +18057,7 @@ UA_Float_copy(const UA_Float *src, UA_Float *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_FLOAT]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_Float_deleteMembers(UA_Float *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_FLOAT]);
}
@@ -17137,7 +18088,7 @@ UA_Double_copy(const UA_Double *src, UA_Double *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_DOUBLE]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_Double_deleteMembers(UA_Double *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_DOUBLE]);
}
@@ -17168,7 +18119,7 @@ UA_String_copy(const UA_String *src, UA_String *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_STRING]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_String_deleteMembers(UA_String *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_STRING]);
}
@@ -17199,7 +18150,7 @@ UA_DateTime_copy(const UA_DateTime *src, UA_DateTime *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_DATETIME]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_DateTime_deleteMembers(UA_DateTime *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_DATETIME]);
}
@@ -17230,7 +18181,7 @@ UA_Guid_copy(const UA_Guid *src, UA_Guid *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_GUID]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_Guid_deleteMembers(UA_Guid *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_GUID]);
}
@@ -17261,7 +18212,7 @@ UA_ByteString_copy(const UA_ByteString *src, UA_ByteString *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_BYTESTRING]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_ByteString_deleteMembers(UA_ByteString *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_BYTESTRING]);
}
@@ -17292,7 +18243,7 @@ UA_XmlElement_copy(const UA_XmlElement *src, UA_XmlElement *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_XMLELEMENT]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_XmlElement_deleteMembers(UA_XmlElement *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_XMLELEMENT]);
}
@@ -17323,7 +18274,7 @@ UA_NodeId_copy(const UA_NodeId *src, UA_NodeId *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_NODEID]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_NodeId_deleteMembers(UA_NodeId *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_NODEID]);
}
@@ -17354,7 +18305,7 @@ UA_ExpandedNodeId_copy(const UA_ExpandedNodeId *src, UA_ExpandedNodeId *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_EXPANDEDNODEID]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_ExpandedNodeId_deleteMembers(UA_ExpandedNodeId *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_EXPANDEDNODEID]);
}
@@ -17385,7 +18336,7 @@ UA_StatusCode_copy(const UA_StatusCode *src, UA_StatusCode *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_STATUSCODE]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_StatusCode_deleteMembers(UA_StatusCode *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_STATUSCODE]);
}
@@ -17416,7 +18367,7 @@ UA_QualifiedName_copy(const UA_QualifiedName *src, UA_QualifiedName *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_QUALIFIEDNAME]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_QualifiedName_deleteMembers(UA_QualifiedName *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_QUALIFIEDNAME]);
}
@@ -17447,7 +18398,7 @@ UA_LocalizedText_copy(const UA_LocalizedText *src, UA_LocalizedText *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_LocalizedText_deleteMembers(UA_LocalizedText *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]);
}
@@ -17478,7 +18429,7 @@ UA_ExtensionObject_copy(const UA_ExtensionObject *src, UA_ExtensionObject *dst)
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_EXTENSIONOBJECT]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_ExtensionObject_deleteMembers(UA_ExtensionObject *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_EXTENSIONOBJECT]);
}
@@ -17509,7 +18460,7 @@ UA_DataValue_copy(const UA_DataValue *src, UA_DataValue *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_DATAVALUE]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_DataValue_deleteMembers(UA_DataValue *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_DATAVALUE]);
}
@@ -17540,7 +18491,7 @@ UA_Variant_copy(const UA_Variant *src, UA_Variant *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_VARIANT]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_Variant_deleteMembers(UA_Variant *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_VARIANT]);
}
@@ -17571,7 +18522,7 @@ UA_DiagnosticInfo_copy(const UA_DiagnosticInfo *src, UA_DiagnosticInfo *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_DIAGNOSTICINFO]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_DiagnosticInfo_deleteMembers(UA_DiagnosticInfo *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_DIAGNOSTICINFO]);
}
@@ -17586,6 +18537,37 @@ UA_DiagnosticInfo_delete(UA_DiagnosticInfo *p) {
UA_delete(p, &UA_TYPES[UA_TYPES_DIAGNOSTICINFO]);
}
+/* KeyValuePair */
+static UA_INLINE void
+UA_KeyValuePair_init(UA_KeyValuePair *p) {
+ memset(p, 0, sizeof(UA_KeyValuePair));
+}
+
+static UA_INLINE UA_KeyValuePair *
+UA_KeyValuePair_new(void) {
+ return (UA_KeyValuePair*)UA_new(&UA_TYPES[UA_TYPES_KEYVALUEPAIR]);
+}
+
+static UA_INLINE UA_StatusCode
+UA_KeyValuePair_copy(const UA_KeyValuePair *src, UA_KeyValuePair *dst) {
+ return UA_copy(src, dst, &UA_TYPES[UA_TYPES_KEYVALUEPAIR]);
+}
+
+UA_DEPRECATED static UA_INLINE void
+UA_KeyValuePair_deleteMembers(UA_KeyValuePair *p) {
+ UA_clear(p, &UA_TYPES[UA_TYPES_KEYVALUEPAIR]);
+}
+
+static UA_INLINE void
+UA_KeyValuePair_clear(UA_KeyValuePair *p) {
+ UA_clear(p, &UA_TYPES[UA_TYPES_KEYVALUEPAIR]);
+}
+
+static UA_INLINE void
+UA_KeyValuePair_delete(UA_KeyValuePair *p) {
+ UA_delete(p, &UA_TYPES[UA_TYPES_KEYVALUEPAIR]);
+}
+
/* NodeClass */
static UA_INLINE void
UA_NodeClass_init(UA_NodeClass *p) {
@@ -17602,7 +18584,7 @@ UA_NodeClass_copy(const UA_NodeClass *src, UA_NodeClass *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_NODECLASS]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_NodeClass_deleteMembers(UA_NodeClass *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_NODECLASS]);
}
@@ -17633,7 +18615,7 @@ UA_StructureType_copy(const UA_StructureType *src, UA_StructureType *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_STRUCTURETYPE]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_StructureType_deleteMembers(UA_StructureType *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_STRUCTURETYPE]);
}
@@ -17664,7 +18646,7 @@ UA_StructureField_copy(const UA_StructureField *src, UA_StructureField *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_STRUCTUREFIELD]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_StructureField_deleteMembers(UA_StructureField *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_STRUCTUREFIELD]);
}
@@ -17695,7 +18677,7 @@ UA_StructureDefinition_copy(const UA_StructureDefinition *src, UA_StructureDefin
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_STRUCTUREDEFINITION]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_StructureDefinition_deleteMembers(UA_StructureDefinition *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_STRUCTUREDEFINITION]);
}
@@ -17726,7 +18708,7 @@ UA_Argument_copy(const UA_Argument *src, UA_Argument *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_ARGUMENT]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_Argument_deleteMembers(UA_Argument *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_ARGUMENT]);
}
@@ -17757,7 +18739,7 @@ UA_EnumValueType_copy(const UA_EnumValueType *src, UA_EnumValueType *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_ENUMVALUETYPE]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_EnumValueType_deleteMembers(UA_EnumValueType *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_ENUMVALUETYPE]);
}
@@ -17788,7 +18770,7 @@ UA_EnumField_copy(const UA_EnumField *src, UA_EnumField *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_ENUMFIELD]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_EnumField_deleteMembers(UA_EnumField *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_ENUMFIELD]);
}
@@ -17819,7 +18801,7 @@ UA_Duration_copy(const UA_Duration *src, UA_Duration *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_DURATION]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_Duration_deleteMembers(UA_Duration *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_DURATION]);
}
@@ -17850,7 +18832,7 @@ UA_UtcTime_copy(const UA_UtcTime *src, UA_UtcTime *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_UTCTIME]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_UtcTime_deleteMembers(UA_UtcTime *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_UTCTIME]);
}
@@ -17881,7 +18863,7 @@ UA_LocaleId_copy(const UA_LocaleId *src, UA_LocaleId *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_LOCALEID]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_LocaleId_deleteMembers(UA_LocaleId *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_LOCALEID]);
}
@@ -17912,7 +18894,7 @@ UA_TimeZoneDataType_copy(const UA_TimeZoneDataType *src, UA_TimeZoneDataType *ds
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_TIMEZONEDATATYPE]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_TimeZoneDataType_deleteMembers(UA_TimeZoneDataType *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_TIMEZONEDATATYPE]);
}
@@ -17943,7 +18925,7 @@ UA_ApplicationType_copy(const UA_ApplicationType *src, UA_ApplicationType *dst)
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_APPLICATIONTYPE]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_ApplicationType_deleteMembers(UA_ApplicationType *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_APPLICATIONTYPE]);
}
@@ -17974,7 +18956,7 @@ UA_ApplicationDescription_copy(const UA_ApplicationDescription *src, UA_Applicat
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_APPLICATIONDESCRIPTION]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_ApplicationDescription_deleteMembers(UA_ApplicationDescription *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_APPLICATIONDESCRIPTION]);
}
@@ -18005,7 +18987,7 @@ UA_RequestHeader_copy(const UA_RequestHeader *src, UA_RequestHeader *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_REQUESTHEADER]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_RequestHeader_deleteMembers(UA_RequestHeader *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_REQUESTHEADER]);
}
@@ -18036,7 +19018,7 @@ UA_ResponseHeader_copy(const UA_ResponseHeader *src, UA_ResponseHeader *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_RESPONSEHEADER]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_ResponseHeader_deleteMembers(UA_ResponseHeader *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_RESPONSEHEADER]);
}
@@ -18067,7 +19049,7 @@ UA_ServiceFault_copy(const UA_ServiceFault *src, UA_ServiceFault *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_SERVICEFAULT]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_ServiceFault_deleteMembers(UA_ServiceFault *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_SERVICEFAULT]);
}
@@ -18098,7 +19080,7 @@ UA_FindServersRequest_copy(const UA_FindServersRequest *src, UA_FindServersReque
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_FINDSERVERSREQUEST]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_FindServersRequest_deleteMembers(UA_FindServersRequest *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_FINDSERVERSREQUEST]);
}
@@ -18129,7 +19111,7 @@ UA_FindServersResponse_copy(const UA_FindServersResponse *src, UA_FindServersRes
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_FINDSERVERSRESPONSE]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_FindServersResponse_deleteMembers(UA_FindServersResponse *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_FINDSERVERSRESPONSE]);
}
@@ -18160,7 +19142,7 @@ UA_MessageSecurityMode_copy(const UA_MessageSecurityMode *src, UA_MessageSecurit
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_MESSAGESECURITYMODE]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_MessageSecurityMode_deleteMembers(UA_MessageSecurityMode *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_MESSAGESECURITYMODE]);
}
@@ -18191,7 +19173,7 @@ UA_UserTokenType_copy(const UA_UserTokenType *src, UA_UserTokenType *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_USERTOKENTYPE]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_UserTokenType_deleteMembers(UA_UserTokenType *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_USERTOKENTYPE]);
}
@@ -18222,7 +19204,7 @@ UA_UserTokenPolicy_copy(const UA_UserTokenPolicy *src, UA_UserTokenPolicy *dst)
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_USERTOKENPOLICY]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_UserTokenPolicy_deleteMembers(UA_UserTokenPolicy *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_USERTOKENPOLICY]);
}
@@ -18253,7 +19235,7 @@ UA_EndpointDescription_copy(const UA_EndpointDescription *src, UA_EndpointDescri
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_EndpointDescription_deleteMembers(UA_EndpointDescription *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION]);
}
@@ -18284,7 +19266,7 @@ UA_GetEndpointsRequest_copy(const UA_GetEndpointsRequest *src, UA_GetEndpointsRe
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_GETENDPOINTSREQUEST]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_GetEndpointsRequest_deleteMembers(UA_GetEndpointsRequest *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_GETENDPOINTSREQUEST]);
}
@@ -18315,7 +19297,7 @@ UA_GetEndpointsResponse_copy(const UA_GetEndpointsResponse *src, UA_GetEndpoints
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_GETENDPOINTSRESPONSE]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_GetEndpointsResponse_deleteMembers(UA_GetEndpointsResponse *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_GETENDPOINTSRESPONSE]);
}
@@ -18346,7 +19328,7 @@ UA_SecurityTokenRequestType_copy(const UA_SecurityTokenRequestType *src, UA_Secu
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_SECURITYTOKENREQUESTTYPE]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_SecurityTokenRequestType_deleteMembers(UA_SecurityTokenRequestType *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_SECURITYTOKENREQUESTTYPE]);
}
@@ -18377,7 +19359,7 @@ UA_ChannelSecurityToken_copy(const UA_ChannelSecurityToken *src, UA_ChannelSecur
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_CHANNELSECURITYTOKEN]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_ChannelSecurityToken_deleteMembers(UA_ChannelSecurityToken *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_CHANNELSECURITYTOKEN]);
}
@@ -18408,7 +19390,7 @@ UA_OpenSecureChannelRequest_copy(const UA_OpenSecureChannelRequest *src, UA_Open
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_OPENSECURECHANNELREQUEST]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_OpenSecureChannelRequest_deleteMembers(UA_OpenSecureChannelRequest *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_OPENSECURECHANNELREQUEST]);
}
@@ -18439,7 +19421,7 @@ UA_OpenSecureChannelResponse_copy(const UA_OpenSecureChannelResponse *src, UA_Op
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_OPENSECURECHANNELRESPONSE]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_OpenSecureChannelResponse_deleteMembers(UA_OpenSecureChannelResponse *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_OPENSECURECHANNELRESPONSE]);
}
@@ -18470,7 +19452,7 @@ UA_CloseSecureChannelRequest_copy(const UA_CloseSecureChannelRequest *src, UA_Cl
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_CLOSESECURECHANNELREQUEST]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_CloseSecureChannelRequest_deleteMembers(UA_CloseSecureChannelRequest *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_CLOSESECURECHANNELREQUEST]);
}
@@ -18501,7 +19483,7 @@ UA_CloseSecureChannelResponse_copy(const UA_CloseSecureChannelResponse *src, UA_
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_CLOSESECURECHANNELRESPONSE]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_CloseSecureChannelResponse_deleteMembers(UA_CloseSecureChannelResponse *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_CLOSESECURECHANNELRESPONSE]);
}
@@ -18532,7 +19514,7 @@ UA_SignedSoftwareCertificate_copy(const UA_SignedSoftwareCertificate *src, UA_Si
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_SIGNEDSOFTWARECERTIFICATE]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_SignedSoftwareCertificate_deleteMembers(UA_SignedSoftwareCertificate *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_SIGNEDSOFTWARECERTIFICATE]);
}
@@ -18563,7 +19545,7 @@ UA_SignatureData_copy(const UA_SignatureData *src, UA_SignatureData *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_SIGNATUREDATA]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_SignatureData_deleteMembers(UA_SignatureData *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_SIGNATUREDATA]);
}
@@ -18594,7 +19576,7 @@ UA_CreateSessionRequest_copy(const UA_CreateSessionRequest *src, UA_CreateSessio
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_CREATESESSIONREQUEST]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_CreateSessionRequest_deleteMembers(UA_CreateSessionRequest *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_CREATESESSIONREQUEST]);
}
@@ -18625,7 +19607,7 @@ UA_CreateSessionResponse_copy(const UA_CreateSessionResponse *src, UA_CreateSess
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_CREATESESSIONRESPONSE]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_CreateSessionResponse_deleteMembers(UA_CreateSessionResponse *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_CREATESESSIONRESPONSE]);
}
@@ -18656,7 +19638,7 @@ UA_UserIdentityToken_copy(const UA_UserIdentityToken *src, UA_UserIdentityToken
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_USERIDENTITYTOKEN]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_UserIdentityToken_deleteMembers(UA_UserIdentityToken *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_USERIDENTITYTOKEN]);
}
@@ -18687,7 +19669,7 @@ UA_AnonymousIdentityToken_copy(const UA_AnonymousIdentityToken *src, UA_Anonymou
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_ANONYMOUSIDENTITYTOKEN]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_AnonymousIdentityToken_deleteMembers(UA_AnonymousIdentityToken *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_ANONYMOUSIDENTITYTOKEN]);
}
@@ -18718,7 +19700,7 @@ UA_UserNameIdentityToken_copy(const UA_UserNameIdentityToken *src, UA_UserNameId
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_USERNAMEIDENTITYTOKEN]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_UserNameIdentityToken_deleteMembers(UA_UserNameIdentityToken *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_USERNAMEIDENTITYTOKEN]);
}
@@ -18749,7 +19731,7 @@ UA_X509IdentityToken_copy(const UA_X509IdentityToken *src, UA_X509IdentityToken
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_X509IDENTITYTOKEN]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_X509IdentityToken_deleteMembers(UA_X509IdentityToken *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_X509IDENTITYTOKEN]);
}
@@ -18780,7 +19762,7 @@ UA_IssuedIdentityToken_copy(const UA_IssuedIdentityToken *src, UA_IssuedIdentity
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_ISSUEDIDENTITYTOKEN]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_IssuedIdentityToken_deleteMembers(UA_IssuedIdentityToken *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_ISSUEDIDENTITYTOKEN]);
}
@@ -18811,7 +19793,7 @@ UA_ActivateSessionRequest_copy(const UA_ActivateSessionRequest *src, UA_Activate
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_ACTIVATESESSIONREQUEST]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_ActivateSessionRequest_deleteMembers(UA_ActivateSessionRequest *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_ACTIVATESESSIONREQUEST]);
}
@@ -18842,7 +19824,7 @@ UA_ActivateSessionResponse_copy(const UA_ActivateSessionResponse *src, UA_Activa
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_ACTIVATESESSIONRESPONSE]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_ActivateSessionResponse_deleteMembers(UA_ActivateSessionResponse *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_ACTIVATESESSIONRESPONSE]);
}
@@ -18873,7 +19855,7 @@ UA_CloseSessionRequest_copy(const UA_CloseSessionRequest *src, UA_CloseSessionRe
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_CLOSESESSIONREQUEST]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_CloseSessionRequest_deleteMembers(UA_CloseSessionRequest *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_CLOSESESSIONREQUEST]);
}
@@ -18904,7 +19886,7 @@ UA_CloseSessionResponse_copy(const UA_CloseSessionResponse *src, UA_CloseSession
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_CLOSESESSIONRESPONSE]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_CloseSessionResponse_deleteMembers(UA_CloseSessionResponse *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_CLOSESESSIONRESPONSE]);
}
@@ -18935,7 +19917,7 @@ UA_NodeAttributesMask_copy(const UA_NodeAttributesMask *src, UA_NodeAttributesMa
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_NODEATTRIBUTESMASK]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_NodeAttributesMask_deleteMembers(UA_NodeAttributesMask *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_NODEATTRIBUTESMASK]);
}
@@ -18966,7 +19948,7 @@ UA_NodeAttributes_copy(const UA_NodeAttributes *src, UA_NodeAttributes *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_NODEATTRIBUTES]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_NodeAttributes_deleteMembers(UA_NodeAttributes *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_NODEATTRIBUTES]);
}
@@ -18997,7 +19979,7 @@ UA_ObjectAttributes_copy(const UA_ObjectAttributes *src, UA_ObjectAttributes *ds
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_ObjectAttributes_deleteMembers(UA_ObjectAttributes *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES]);
}
@@ -19028,7 +20010,7 @@ UA_VariableAttributes_copy(const UA_VariableAttributes *src, UA_VariableAttribut
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_VariableAttributes_deleteMembers(UA_VariableAttributes *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES]);
}
@@ -19059,7 +20041,7 @@ UA_MethodAttributes_copy(const UA_MethodAttributes *src, UA_MethodAttributes *ds
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_METHODATTRIBUTES]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_MethodAttributes_deleteMembers(UA_MethodAttributes *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_METHODATTRIBUTES]);
}
@@ -19090,7 +20072,7 @@ UA_ObjectTypeAttributes_copy(const UA_ObjectTypeAttributes *src, UA_ObjectTypeAt
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_ObjectTypeAttributes_deleteMembers(UA_ObjectTypeAttributes *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES]);
}
@@ -19121,7 +20103,7 @@ UA_VariableTypeAttributes_copy(const UA_VariableTypeAttributes *src, UA_Variable
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_VariableTypeAttributes_deleteMembers(UA_VariableTypeAttributes *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES]);
}
@@ -19152,7 +20134,7 @@ UA_ReferenceTypeAttributes_copy(const UA_ReferenceTypeAttributes *src, UA_Refere
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_ReferenceTypeAttributes_deleteMembers(UA_ReferenceTypeAttributes *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES]);
}
@@ -19183,7 +20165,7 @@ UA_DataTypeAttributes_copy(const UA_DataTypeAttributes *src, UA_DataTypeAttribut
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_DataTypeAttributes_deleteMembers(UA_DataTypeAttributes *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES]);
}
@@ -19214,7 +20196,7 @@ UA_ViewAttributes_copy(const UA_ViewAttributes *src, UA_ViewAttributes *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_VIEWATTRIBUTES]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_ViewAttributes_deleteMembers(UA_ViewAttributes *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_VIEWATTRIBUTES]);
}
@@ -19245,7 +20227,7 @@ UA_AddNodesItem_copy(const UA_AddNodesItem *src, UA_AddNodesItem *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_ADDNODESITEM]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_AddNodesItem_deleteMembers(UA_AddNodesItem *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_ADDNODESITEM]);
}
@@ -19276,7 +20258,7 @@ UA_AddNodesResult_copy(const UA_AddNodesResult *src, UA_AddNodesResult *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_ADDNODESRESULT]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_AddNodesResult_deleteMembers(UA_AddNodesResult *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_ADDNODESRESULT]);
}
@@ -19307,7 +20289,7 @@ UA_AddNodesRequest_copy(const UA_AddNodesRequest *src, UA_AddNodesRequest *dst)
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_ADDNODESREQUEST]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_AddNodesRequest_deleteMembers(UA_AddNodesRequest *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_ADDNODESREQUEST]);
}
@@ -19338,7 +20320,7 @@ UA_AddNodesResponse_copy(const UA_AddNodesResponse *src, UA_AddNodesResponse *ds
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_ADDNODESRESPONSE]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_AddNodesResponse_deleteMembers(UA_AddNodesResponse *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_ADDNODESRESPONSE]);
}
@@ -19369,7 +20351,7 @@ UA_AddReferencesItem_copy(const UA_AddReferencesItem *src, UA_AddReferencesItem
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_ADDREFERENCESITEM]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_AddReferencesItem_deleteMembers(UA_AddReferencesItem *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_ADDREFERENCESITEM]);
}
@@ -19400,7 +20382,7 @@ UA_AddReferencesRequest_copy(const UA_AddReferencesRequest *src, UA_AddReference
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_ADDREFERENCESREQUEST]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_AddReferencesRequest_deleteMembers(UA_AddReferencesRequest *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_ADDREFERENCESREQUEST]);
}
@@ -19431,7 +20413,7 @@ UA_AddReferencesResponse_copy(const UA_AddReferencesResponse *src, UA_AddReferen
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_ADDREFERENCESRESPONSE]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_AddReferencesResponse_deleteMembers(UA_AddReferencesResponse *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_ADDREFERENCESRESPONSE]);
}
@@ -19462,7 +20444,7 @@ UA_DeleteNodesItem_copy(const UA_DeleteNodesItem *src, UA_DeleteNodesItem *dst)
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_DELETENODESITEM]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_DeleteNodesItem_deleteMembers(UA_DeleteNodesItem *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_DELETENODESITEM]);
}
@@ -19493,7 +20475,7 @@ UA_DeleteNodesRequest_copy(const UA_DeleteNodesRequest *src, UA_DeleteNodesReque
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_DELETENODESREQUEST]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_DeleteNodesRequest_deleteMembers(UA_DeleteNodesRequest *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_DELETENODESREQUEST]);
}
@@ -19524,7 +20506,7 @@ UA_DeleteNodesResponse_copy(const UA_DeleteNodesResponse *src, UA_DeleteNodesRes
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_DELETENODESRESPONSE]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_DeleteNodesResponse_deleteMembers(UA_DeleteNodesResponse *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_DELETENODESRESPONSE]);
}
@@ -19555,7 +20537,7 @@ UA_DeleteReferencesItem_copy(const UA_DeleteReferencesItem *src, UA_DeleteRefere
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_DELETEREFERENCESITEM]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_DeleteReferencesItem_deleteMembers(UA_DeleteReferencesItem *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_DELETEREFERENCESITEM]);
}
@@ -19586,7 +20568,7 @@ UA_DeleteReferencesRequest_copy(const UA_DeleteReferencesRequest *src, UA_Delete
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_DELETEREFERENCESREQUEST]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_DeleteReferencesRequest_deleteMembers(UA_DeleteReferencesRequest *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_DELETEREFERENCESREQUEST]);
}
@@ -19617,7 +20599,7 @@ UA_DeleteReferencesResponse_copy(const UA_DeleteReferencesResponse *src, UA_Dele
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_DELETEREFERENCESRESPONSE]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_DeleteReferencesResponse_deleteMembers(UA_DeleteReferencesResponse *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_DELETEREFERENCESRESPONSE]);
}
@@ -19648,7 +20630,7 @@ UA_BrowseDirection_copy(const UA_BrowseDirection *src, UA_BrowseDirection *dst)
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_BROWSEDIRECTION]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_BrowseDirection_deleteMembers(UA_BrowseDirection *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_BROWSEDIRECTION]);
}
@@ -19679,7 +20661,7 @@ UA_ViewDescription_copy(const UA_ViewDescription *src, UA_ViewDescription *dst)
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_VIEWDESCRIPTION]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_ViewDescription_deleteMembers(UA_ViewDescription *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_VIEWDESCRIPTION]);
}
@@ -19710,7 +20692,7 @@ UA_BrowseDescription_copy(const UA_BrowseDescription *src, UA_BrowseDescription
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_BROWSEDESCRIPTION]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_BrowseDescription_deleteMembers(UA_BrowseDescription *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_BROWSEDESCRIPTION]);
}
@@ -19741,7 +20723,7 @@ UA_BrowseResultMask_copy(const UA_BrowseResultMask *src, UA_BrowseResultMask *ds
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_BROWSERESULTMASK]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_BrowseResultMask_deleteMembers(UA_BrowseResultMask *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_BROWSERESULTMASK]);
}
@@ -19772,7 +20754,7 @@ UA_ReferenceDescription_copy(const UA_ReferenceDescription *src, UA_ReferenceDes
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_REFERENCEDESCRIPTION]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_ReferenceDescription_deleteMembers(UA_ReferenceDescription *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_REFERENCEDESCRIPTION]);
}
@@ -19803,7 +20785,7 @@ UA_BrowseResult_copy(const UA_BrowseResult *src, UA_BrowseResult *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_BROWSERESULT]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_BrowseResult_deleteMembers(UA_BrowseResult *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_BROWSERESULT]);
}
@@ -19834,7 +20816,7 @@ UA_BrowseRequest_copy(const UA_BrowseRequest *src, UA_BrowseRequest *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_BROWSEREQUEST]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_BrowseRequest_deleteMembers(UA_BrowseRequest *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_BROWSEREQUEST]);
}
@@ -19865,7 +20847,7 @@ UA_BrowseResponse_copy(const UA_BrowseResponse *src, UA_BrowseResponse *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_BROWSERESPONSE]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_BrowseResponse_deleteMembers(UA_BrowseResponse *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_BROWSERESPONSE]);
}
@@ -19896,7 +20878,7 @@ UA_BrowseNextRequest_copy(const UA_BrowseNextRequest *src, UA_BrowseNextRequest
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_BROWSENEXTREQUEST]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_BrowseNextRequest_deleteMembers(UA_BrowseNextRequest *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_BROWSENEXTREQUEST]);
}
@@ -19927,7 +20909,7 @@ UA_BrowseNextResponse_copy(const UA_BrowseNextResponse *src, UA_BrowseNextRespon
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_BROWSENEXTRESPONSE]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_BrowseNextResponse_deleteMembers(UA_BrowseNextResponse *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_BROWSENEXTRESPONSE]);
}
@@ -19958,7 +20940,7 @@ UA_RelativePathElement_copy(const UA_RelativePathElement *src, UA_RelativePathEl
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_RELATIVEPATHELEMENT]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_RelativePathElement_deleteMembers(UA_RelativePathElement *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_RELATIVEPATHELEMENT]);
}
@@ -19989,7 +20971,7 @@ UA_RelativePath_copy(const UA_RelativePath *src, UA_RelativePath *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_RELATIVEPATH]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_RelativePath_deleteMembers(UA_RelativePath *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_RELATIVEPATH]);
}
@@ -20020,7 +21002,7 @@ UA_BrowsePath_copy(const UA_BrowsePath *src, UA_BrowsePath *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_BROWSEPATH]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_BrowsePath_deleteMembers(UA_BrowsePath *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_BROWSEPATH]);
}
@@ -20051,7 +21033,7 @@ UA_BrowsePathTarget_copy(const UA_BrowsePathTarget *src, UA_BrowsePathTarget *ds
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_BROWSEPATHTARGET]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_BrowsePathTarget_deleteMembers(UA_BrowsePathTarget *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_BROWSEPATHTARGET]);
}
@@ -20082,7 +21064,7 @@ UA_BrowsePathResult_copy(const UA_BrowsePathResult *src, UA_BrowsePathResult *ds
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_BROWSEPATHRESULT]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_BrowsePathResult_deleteMembers(UA_BrowsePathResult *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_BROWSEPATHRESULT]);
}
@@ -20113,7 +21095,7 @@ UA_TranslateBrowsePathsToNodeIdsRequest_copy(const UA_TranslateBrowsePathsToNode
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_TRANSLATEBROWSEPATHSTONODEIDSREQUEST]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_TranslateBrowsePathsToNodeIdsRequest_deleteMembers(UA_TranslateBrowsePathsToNodeIdsRequest *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_TRANSLATEBROWSEPATHSTONODEIDSREQUEST]);
}
@@ -20144,7 +21126,7 @@ UA_TranslateBrowsePathsToNodeIdsResponse_copy(const UA_TranslateBrowsePathsToNod
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_TRANSLATEBROWSEPATHSTONODEIDSRESPONSE]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_TranslateBrowsePathsToNodeIdsResponse_deleteMembers(UA_TranslateBrowsePathsToNodeIdsResponse *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_TRANSLATEBROWSEPATHSTONODEIDSRESPONSE]);
}
@@ -20175,7 +21157,7 @@ UA_RegisterNodesRequest_copy(const UA_RegisterNodesRequest *src, UA_RegisterNode
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_REGISTERNODESREQUEST]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_RegisterNodesRequest_deleteMembers(UA_RegisterNodesRequest *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_REGISTERNODESREQUEST]);
}
@@ -20206,7 +21188,7 @@ UA_RegisterNodesResponse_copy(const UA_RegisterNodesResponse *src, UA_RegisterNo
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_REGISTERNODESRESPONSE]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_RegisterNodesResponse_deleteMembers(UA_RegisterNodesResponse *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_REGISTERNODESRESPONSE]);
}
@@ -20237,7 +21219,7 @@ UA_UnregisterNodesRequest_copy(const UA_UnregisterNodesRequest *src, UA_Unregist
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_UNREGISTERNODESREQUEST]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_UnregisterNodesRequest_deleteMembers(UA_UnregisterNodesRequest *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_UNREGISTERNODESREQUEST]);
}
@@ -20268,7 +21250,7 @@ UA_UnregisterNodesResponse_copy(const UA_UnregisterNodesResponse *src, UA_Unregi
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_UNREGISTERNODESRESPONSE]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_UnregisterNodesResponse_deleteMembers(UA_UnregisterNodesResponse *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_UNREGISTERNODESRESPONSE]);
}
@@ -20299,7 +21281,7 @@ UA_FilterOperator_copy(const UA_FilterOperator *src, UA_FilterOperator *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_FILTEROPERATOR]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_FilterOperator_deleteMembers(UA_FilterOperator *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_FILTEROPERATOR]);
}
@@ -20330,7 +21312,7 @@ UA_ContentFilterElement_copy(const UA_ContentFilterElement *src, UA_ContentFilte
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_CONTENTFILTERELEMENT]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_ContentFilterElement_deleteMembers(UA_ContentFilterElement *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_CONTENTFILTERELEMENT]);
}
@@ -20361,7 +21343,7 @@ UA_ContentFilter_copy(const UA_ContentFilter *src, UA_ContentFilter *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_CONTENTFILTER]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_ContentFilter_deleteMembers(UA_ContentFilter *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_CONTENTFILTER]);
}
@@ -20376,37 +21358,6 @@ UA_ContentFilter_delete(UA_ContentFilter *p) {
UA_delete(p, &UA_TYPES[UA_TYPES_CONTENTFILTER]);
}
-/* FilterOperand */
-static UA_INLINE void
-UA_FilterOperand_init(UA_FilterOperand *p) {
- memset(p, 0, sizeof(UA_FilterOperand));
-}
-
-static UA_INLINE UA_FilterOperand *
-UA_FilterOperand_new(void) {
- return (UA_FilterOperand*)UA_new(&UA_TYPES[UA_TYPES_FILTEROPERAND]);
-}
-
-static UA_INLINE UA_StatusCode
-UA_FilterOperand_copy(const UA_FilterOperand *src, UA_FilterOperand *dst) {
- return UA_copy(src, dst, &UA_TYPES[UA_TYPES_FILTEROPERAND]);
-}
-
-static UA_INLINE void
-UA_FilterOperand_deleteMembers(UA_FilterOperand *p) {
- UA_clear(p, &UA_TYPES[UA_TYPES_FILTEROPERAND]);
-}
-
-static UA_INLINE void
-UA_FilterOperand_clear(UA_FilterOperand *p) {
- UA_clear(p, &UA_TYPES[UA_TYPES_FILTEROPERAND]);
-}
-
-static UA_INLINE void
-UA_FilterOperand_delete(UA_FilterOperand *p) {
- UA_delete(p, &UA_TYPES[UA_TYPES_FILTEROPERAND]);
-}
-
/* ElementOperand */
static UA_INLINE void
UA_ElementOperand_init(UA_ElementOperand *p) {
@@ -20423,7 +21374,7 @@ UA_ElementOperand_copy(const UA_ElementOperand *src, UA_ElementOperand *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_ELEMENTOPERAND]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_ElementOperand_deleteMembers(UA_ElementOperand *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_ELEMENTOPERAND]);
}
@@ -20454,7 +21405,7 @@ UA_LiteralOperand_copy(const UA_LiteralOperand *src, UA_LiteralOperand *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_LITERALOPERAND]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_LiteralOperand_deleteMembers(UA_LiteralOperand *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_LITERALOPERAND]);
}
@@ -20485,7 +21436,7 @@ UA_AttributeOperand_copy(const UA_AttributeOperand *src, UA_AttributeOperand *ds
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_ATTRIBUTEOPERAND]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_AttributeOperand_deleteMembers(UA_AttributeOperand *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_ATTRIBUTEOPERAND]);
}
@@ -20516,7 +21467,7 @@ UA_SimpleAttributeOperand_copy(const UA_SimpleAttributeOperand *src, UA_SimpleAt
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_SIMPLEATTRIBUTEOPERAND]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_SimpleAttributeOperand_deleteMembers(UA_SimpleAttributeOperand *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_SIMPLEATTRIBUTEOPERAND]);
}
@@ -20547,7 +21498,7 @@ UA_ContentFilterElementResult_copy(const UA_ContentFilterElementResult *src, UA_
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_CONTENTFILTERELEMENTRESULT]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_ContentFilterElementResult_deleteMembers(UA_ContentFilterElementResult *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_CONTENTFILTERELEMENTRESULT]);
}
@@ -20578,7 +21529,7 @@ UA_ContentFilterResult_copy(const UA_ContentFilterResult *src, UA_ContentFilterR
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_CONTENTFILTERRESULT]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_ContentFilterResult_deleteMembers(UA_ContentFilterResult *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_CONTENTFILTERRESULT]);
}
@@ -20609,7 +21560,7 @@ UA_TimestampsToReturn_copy(const UA_TimestampsToReturn *src, UA_TimestampsToRetu
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_TIMESTAMPSTORETURN]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_TimestampsToReturn_deleteMembers(UA_TimestampsToReturn *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_TIMESTAMPSTORETURN]);
}
@@ -20640,7 +21591,7 @@ UA_ReadValueId_copy(const UA_ReadValueId *src, UA_ReadValueId *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_READVALUEID]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_ReadValueId_deleteMembers(UA_ReadValueId *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_READVALUEID]);
}
@@ -20671,7 +21622,7 @@ UA_ReadRequest_copy(const UA_ReadRequest *src, UA_ReadRequest *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_READREQUEST]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_ReadRequest_deleteMembers(UA_ReadRequest *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_READREQUEST]);
}
@@ -20702,7 +21653,7 @@ UA_ReadResponse_copy(const UA_ReadResponse *src, UA_ReadResponse *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_READRESPONSE]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_ReadResponse_deleteMembers(UA_ReadResponse *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_READRESPONSE]);
}
@@ -20733,7 +21684,7 @@ UA_HistoryReadValueId_copy(const UA_HistoryReadValueId *src, UA_HistoryReadValue
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_HISTORYREADVALUEID]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_HistoryReadValueId_deleteMembers(UA_HistoryReadValueId *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_HISTORYREADVALUEID]);
}
@@ -20764,7 +21715,7 @@ UA_HistoryReadResult_copy(const UA_HistoryReadResult *src, UA_HistoryReadResult
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_HISTORYREADRESULT]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_HistoryReadResult_deleteMembers(UA_HistoryReadResult *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_HISTORYREADRESULT]);
}
@@ -20795,7 +21746,7 @@ UA_ReadRawModifiedDetails_copy(const UA_ReadRawModifiedDetails *src, UA_ReadRawM
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_READRAWMODIFIEDDETAILS]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_ReadRawModifiedDetails_deleteMembers(UA_ReadRawModifiedDetails *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_READRAWMODIFIEDDETAILS]);
}
@@ -20826,7 +21777,7 @@ UA_ReadAtTimeDetails_copy(const UA_ReadAtTimeDetails *src, UA_ReadAtTimeDetails
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_READATTIMEDETAILS]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_ReadAtTimeDetails_deleteMembers(UA_ReadAtTimeDetails *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_READATTIMEDETAILS]);
}
@@ -20857,7 +21808,7 @@ UA_HistoryData_copy(const UA_HistoryData *src, UA_HistoryData *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_HISTORYDATA]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_HistoryData_deleteMembers(UA_HistoryData *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_HISTORYDATA]);
}
@@ -20888,7 +21839,7 @@ UA_HistoryReadRequest_copy(const UA_HistoryReadRequest *src, UA_HistoryReadReque
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_HISTORYREADREQUEST]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_HistoryReadRequest_deleteMembers(UA_HistoryReadRequest *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_HISTORYREADREQUEST]);
}
@@ -20919,7 +21870,7 @@ UA_HistoryReadResponse_copy(const UA_HistoryReadResponse *src, UA_HistoryReadRes
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_HISTORYREADRESPONSE]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_HistoryReadResponse_deleteMembers(UA_HistoryReadResponse *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_HISTORYREADRESPONSE]);
}
@@ -20950,7 +21901,7 @@ UA_WriteValue_copy(const UA_WriteValue *src, UA_WriteValue *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_WRITEVALUE]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_WriteValue_deleteMembers(UA_WriteValue *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_WRITEVALUE]);
}
@@ -20981,7 +21932,7 @@ UA_WriteRequest_copy(const UA_WriteRequest *src, UA_WriteRequest *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_WRITEREQUEST]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_WriteRequest_deleteMembers(UA_WriteRequest *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_WRITEREQUEST]);
}
@@ -21012,7 +21963,7 @@ UA_WriteResponse_copy(const UA_WriteResponse *src, UA_WriteResponse *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_WRITERESPONSE]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_WriteResponse_deleteMembers(UA_WriteResponse *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_WRITERESPONSE]);
}
@@ -21043,7 +21994,7 @@ UA_HistoryUpdateType_copy(const UA_HistoryUpdateType *src, UA_HistoryUpdateType
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_HISTORYUPDATETYPE]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_HistoryUpdateType_deleteMembers(UA_HistoryUpdateType *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_HISTORYUPDATETYPE]);
}
@@ -21074,7 +22025,7 @@ UA_PerformUpdateType_copy(const UA_PerformUpdateType *src, UA_PerformUpdateType
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_PERFORMUPDATETYPE]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_PerformUpdateType_deleteMembers(UA_PerformUpdateType *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_PERFORMUPDATETYPE]);
}
@@ -21105,7 +22056,7 @@ UA_UpdateDataDetails_copy(const UA_UpdateDataDetails *src, UA_UpdateDataDetails
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_UPDATEDATADETAILS]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_UpdateDataDetails_deleteMembers(UA_UpdateDataDetails *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_UPDATEDATADETAILS]);
}
@@ -21136,7 +22087,7 @@ UA_DeleteRawModifiedDetails_copy(const UA_DeleteRawModifiedDetails *src, UA_Dele
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_DELETERAWMODIFIEDDETAILS]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_DeleteRawModifiedDetails_deleteMembers(UA_DeleteRawModifiedDetails *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_DELETERAWMODIFIEDDETAILS]);
}
@@ -21167,7 +22118,7 @@ UA_HistoryUpdateResult_copy(const UA_HistoryUpdateResult *src, UA_HistoryUpdateR
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_HISTORYUPDATERESULT]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_HistoryUpdateResult_deleteMembers(UA_HistoryUpdateResult *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_HISTORYUPDATERESULT]);
}
@@ -21198,7 +22149,7 @@ UA_HistoryUpdateRequest_copy(const UA_HistoryUpdateRequest *src, UA_HistoryUpdat
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_HISTORYUPDATEREQUEST]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_HistoryUpdateRequest_deleteMembers(UA_HistoryUpdateRequest *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_HISTORYUPDATEREQUEST]);
}
@@ -21229,7 +22180,7 @@ UA_HistoryUpdateResponse_copy(const UA_HistoryUpdateResponse *src, UA_HistoryUpd
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_HISTORYUPDATERESPONSE]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_HistoryUpdateResponse_deleteMembers(UA_HistoryUpdateResponse *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_HISTORYUPDATERESPONSE]);
}
@@ -21260,7 +22211,7 @@ UA_CallMethodRequest_copy(const UA_CallMethodRequest *src, UA_CallMethodRequest
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_CALLMETHODREQUEST]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_CallMethodRequest_deleteMembers(UA_CallMethodRequest *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_CALLMETHODREQUEST]);
}
@@ -21291,7 +22242,7 @@ UA_CallMethodResult_copy(const UA_CallMethodResult *src, UA_CallMethodResult *ds
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_CALLMETHODRESULT]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_CallMethodResult_deleteMembers(UA_CallMethodResult *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_CALLMETHODRESULT]);
}
@@ -21322,7 +22273,7 @@ UA_CallRequest_copy(const UA_CallRequest *src, UA_CallRequest *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_CALLREQUEST]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_CallRequest_deleteMembers(UA_CallRequest *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_CALLREQUEST]);
}
@@ -21353,7 +22304,7 @@ UA_CallResponse_copy(const UA_CallResponse *src, UA_CallResponse *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_CALLRESPONSE]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_CallResponse_deleteMembers(UA_CallResponse *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_CALLRESPONSE]);
}
@@ -21384,7 +22335,7 @@ UA_MonitoringMode_copy(const UA_MonitoringMode *src, UA_MonitoringMode *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_MONITORINGMODE]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_MonitoringMode_deleteMembers(UA_MonitoringMode *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_MONITORINGMODE]);
}
@@ -21415,7 +22366,7 @@ UA_DataChangeTrigger_copy(const UA_DataChangeTrigger *src, UA_DataChangeTrigger
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_DATACHANGETRIGGER]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_DataChangeTrigger_deleteMembers(UA_DataChangeTrigger *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_DATACHANGETRIGGER]);
}
@@ -21446,7 +22397,7 @@ UA_DeadbandType_copy(const UA_DeadbandType *src, UA_DeadbandType *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_DEADBANDTYPE]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_DeadbandType_deleteMembers(UA_DeadbandType *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_DEADBANDTYPE]);
}
@@ -21477,7 +22428,7 @@ UA_DataChangeFilter_copy(const UA_DataChangeFilter *src, UA_DataChangeFilter *ds
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_DATACHANGEFILTER]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_DataChangeFilter_deleteMembers(UA_DataChangeFilter *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_DATACHANGEFILTER]);
}
@@ -21508,7 +22459,7 @@ UA_EventFilter_copy(const UA_EventFilter *src, UA_EventFilter *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_EVENTFILTER]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_EventFilter_deleteMembers(UA_EventFilter *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_EVENTFILTER]);
}
@@ -21539,7 +22490,7 @@ UA_AggregateConfiguration_copy(const UA_AggregateConfiguration *src, UA_Aggregat
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_AGGREGATECONFIGURATION]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_AggregateConfiguration_deleteMembers(UA_AggregateConfiguration *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_AGGREGATECONFIGURATION]);
}
@@ -21570,7 +22521,7 @@ UA_AggregateFilter_copy(const UA_AggregateFilter *src, UA_AggregateFilter *dst)
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_AGGREGATEFILTER]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_AggregateFilter_deleteMembers(UA_AggregateFilter *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_AGGREGATEFILTER]);
}
@@ -21601,7 +22552,7 @@ UA_EventFilterResult_copy(const UA_EventFilterResult *src, UA_EventFilterResult
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_EVENTFILTERRESULT]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_EventFilterResult_deleteMembers(UA_EventFilterResult *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_EVENTFILTERRESULT]);
}
@@ -21632,7 +22583,7 @@ UA_MonitoringParameters_copy(const UA_MonitoringParameters *src, UA_MonitoringPa
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_MONITORINGPARAMETERS]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_MonitoringParameters_deleteMembers(UA_MonitoringParameters *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_MONITORINGPARAMETERS]);
}
@@ -21663,7 +22614,7 @@ UA_MonitoredItemCreateRequest_copy(const UA_MonitoredItemCreateRequest *src, UA_
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_MONITOREDITEMCREATEREQUEST]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_MonitoredItemCreateRequest_deleteMembers(UA_MonitoredItemCreateRequest *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_MONITOREDITEMCREATEREQUEST]);
}
@@ -21694,7 +22645,7 @@ UA_MonitoredItemCreateResult_copy(const UA_MonitoredItemCreateResult *src, UA_Mo
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_MONITOREDITEMCREATERESULT]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_MonitoredItemCreateResult_deleteMembers(UA_MonitoredItemCreateResult *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_MONITOREDITEMCREATERESULT]);
}
@@ -21725,7 +22676,7 @@ UA_CreateMonitoredItemsRequest_copy(const UA_CreateMonitoredItemsRequest *src, U
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_CREATEMONITOREDITEMSREQUEST]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_CreateMonitoredItemsRequest_deleteMembers(UA_CreateMonitoredItemsRequest *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_CREATEMONITOREDITEMSREQUEST]);
}
@@ -21756,7 +22707,7 @@ UA_CreateMonitoredItemsResponse_copy(const UA_CreateMonitoredItemsResponse *src,
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_CREATEMONITOREDITEMSRESPONSE]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_CreateMonitoredItemsResponse_deleteMembers(UA_CreateMonitoredItemsResponse *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_CREATEMONITOREDITEMSRESPONSE]);
}
@@ -21787,7 +22738,7 @@ UA_MonitoredItemModifyRequest_copy(const UA_MonitoredItemModifyRequest *src, UA_
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_MONITOREDITEMMODIFYREQUEST]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_MonitoredItemModifyRequest_deleteMembers(UA_MonitoredItemModifyRequest *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_MONITOREDITEMMODIFYREQUEST]);
}
@@ -21818,7 +22769,7 @@ UA_MonitoredItemModifyResult_copy(const UA_MonitoredItemModifyResult *src, UA_Mo
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_MONITOREDITEMMODIFYRESULT]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_MonitoredItemModifyResult_deleteMembers(UA_MonitoredItemModifyResult *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_MONITOREDITEMMODIFYRESULT]);
}
@@ -21849,7 +22800,7 @@ UA_ModifyMonitoredItemsRequest_copy(const UA_ModifyMonitoredItemsRequest *src, U
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_MODIFYMONITOREDITEMSREQUEST]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_ModifyMonitoredItemsRequest_deleteMembers(UA_ModifyMonitoredItemsRequest *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_MODIFYMONITOREDITEMSREQUEST]);
}
@@ -21880,7 +22831,7 @@ UA_ModifyMonitoredItemsResponse_copy(const UA_ModifyMonitoredItemsResponse *src,
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_MODIFYMONITOREDITEMSRESPONSE]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_ModifyMonitoredItemsResponse_deleteMembers(UA_ModifyMonitoredItemsResponse *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_MODIFYMONITOREDITEMSRESPONSE]);
}
@@ -21911,7 +22862,7 @@ UA_SetMonitoringModeRequest_copy(const UA_SetMonitoringModeRequest *src, UA_SetM
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_SETMONITORINGMODEREQUEST]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_SetMonitoringModeRequest_deleteMembers(UA_SetMonitoringModeRequest *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_SETMONITORINGMODEREQUEST]);
}
@@ -21942,7 +22893,7 @@ UA_SetMonitoringModeResponse_copy(const UA_SetMonitoringModeResponse *src, UA_Se
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_SETMONITORINGMODERESPONSE]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_SetMonitoringModeResponse_deleteMembers(UA_SetMonitoringModeResponse *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_SETMONITORINGMODERESPONSE]);
}
@@ -21973,7 +22924,7 @@ UA_SetTriggeringRequest_copy(const UA_SetTriggeringRequest *src, UA_SetTriggerin
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_SETTRIGGERINGREQUEST]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_SetTriggeringRequest_deleteMembers(UA_SetTriggeringRequest *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_SETTRIGGERINGREQUEST]);
}
@@ -22004,7 +22955,7 @@ UA_SetTriggeringResponse_copy(const UA_SetTriggeringResponse *src, UA_SetTrigger
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_SETTRIGGERINGRESPONSE]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_SetTriggeringResponse_deleteMembers(UA_SetTriggeringResponse *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_SETTRIGGERINGRESPONSE]);
}
@@ -22035,7 +22986,7 @@ UA_DeleteMonitoredItemsRequest_copy(const UA_DeleteMonitoredItemsRequest *src, U
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_DELETEMONITOREDITEMSREQUEST]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_DeleteMonitoredItemsRequest_deleteMembers(UA_DeleteMonitoredItemsRequest *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_DELETEMONITOREDITEMSREQUEST]);
}
@@ -22066,7 +23017,7 @@ UA_DeleteMonitoredItemsResponse_copy(const UA_DeleteMonitoredItemsResponse *src,
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_DELETEMONITOREDITEMSRESPONSE]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_DeleteMonitoredItemsResponse_deleteMembers(UA_DeleteMonitoredItemsResponse *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_DELETEMONITOREDITEMSRESPONSE]);
}
@@ -22097,7 +23048,7 @@ UA_CreateSubscriptionRequest_copy(const UA_CreateSubscriptionRequest *src, UA_Cr
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_CREATESUBSCRIPTIONREQUEST]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_CreateSubscriptionRequest_deleteMembers(UA_CreateSubscriptionRequest *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_CREATESUBSCRIPTIONREQUEST]);
}
@@ -22128,7 +23079,7 @@ UA_CreateSubscriptionResponse_copy(const UA_CreateSubscriptionResponse *src, UA_
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_CREATESUBSCRIPTIONRESPONSE]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_CreateSubscriptionResponse_deleteMembers(UA_CreateSubscriptionResponse *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_CREATESUBSCRIPTIONRESPONSE]);
}
@@ -22159,7 +23110,7 @@ UA_ModifySubscriptionRequest_copy(const UA_ModifySubscriptionRequest *src, UA_Mo
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_MODIFYSUBSCRIPTIONREQUEST]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_ModifySubscriptionRequest_deleteMembers(UA_ModifySubscriptionRequest *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_MODIFYSUBSCRIPTIONREQUEST]);
}
@@ -22190,7 +23141,7 @@ UA_ModifySubscriptionResponse_copy(const UA_ModifySubscriptionResponse *src, UA_
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_MODIFYSUBSCRIPTIONRESPONSE]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_ModifySubscriptionResponse_deleteMembers(UA_ModifySubscriptionResponse *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_MODIFYSUBSCRIPTIONRESPONSE]);
}
@@ -22221,7 +23172,7 @@ UA_SetPublishingModeRequest_copy(const UA_SetPublishingModeRequest *src, UA_SetP
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_SETPUBLISHINGMODEREQUEST]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_SetPublishingModeRequest_deleteMembers(UA_SetPublishingModeRequest *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_SETPUBLISHINGMODEREQUEST]);
}
@@ -22252,7 +23203,7 @@ UA_SetPublishingModeResponse_copy(const UA_SetPublishingModeResponse *src, UA_Se
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_SETPUBLISHINGMODERESPONSE]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_SetPublishingModeResponse_deleteMembers(UA_SetPublishingModeResponse *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_SETPUBLISHINGMODERESPONSE]);
}
@@ -22283,7 +23234,7 @@ UA_NotificationMessage_copy(const UA_NotificationMessage *src, UA_NotificationMe
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_NOTIFICATIONMESSAGE]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_NotificationMessage_deleteMembers(UA_NotificationMessage *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_NOTIFICATIONMESSAGE]);
}
@@ -22314,7 +23265,7 @@ UA_MonitoredItemNotification_copy(const UA_MonitoredItemNotification *src, UA_Mo
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_MONITOREDITEMNOTIFICATION]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_MonitoredItemNotification_deleteMembers(UA_MonitoredItemNotification *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_MONITOREDITEMNOTIFICATION]);
}
@@ -22345,7 +23296,7 @@ UA_EventFieldList_copy(const UA_EventFieldList *src, UA_EventFieldList *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_EVENTFIELDLIST]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_EventFieldList_deleteMembers(UA_EventFieldList *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_EVENTFIELDLIST]);
}
@@ -22376,7 +23327,7 @@ UA_HistoryEventFieldList_copy(const UA_HistoryEventFieldList *src, UA_HistoryEve
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_HISTORYEVENTFIELDLIST]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_HistoryEventFieldList_deleteMembers(UA_HistoryEventFieldList *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_HISTORYEVENTFIELDLIST]);
}
@@ -22407,7 +23358,7 @@ UA_StatusChangeNotification_copy(const UA_StatusChangeNotification *src, UA_Stat
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_STATUSCHANGENOTIFICATION]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_StatusChangeNotification_deleteMembers(UA_StatusChangeNotification *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_STATUSCHANGENOTIFICATION]);
}
@@ -22438,7 +23389,7 @@ UA_SubscriptionAcknowledgement_copy(const UA_SubscriptionAcknowledgement *src, U
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_SUBSCRIPTIONACKNOWLEDGEMENT]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_SubscriptionAcknowledgement_deleteMembers(UA_SubscriptionAcknowledgement *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_SUBSCRIPTIONACKNOWLEDGEMENT]);
}
@@ -22469,7 +23420,7 @@ UA_PublishRequest_copy(const UA_PublishRequest *src, UA_PublishRequest *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_PUBLISHREQUEST]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_PublishRequest_deleteMembers(UA_PublishRequest *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_PUBLISHREQUEST]);
}
@@ -22500,7 +23451,7 @@ UA_PublishResponse_copy(const UA_PublishResponse *src, UA_PublishResponse *dst)
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_PUBLISHRESPONSE]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_PublishResponse_deleteMembers(UA_PublishResponse *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_PUBLISHRESPONSE]);
}
@@ -22531,7 +23482,7 @@ UA_RepublishRequest_copy(const UA_RepublishRequest *src, UA_RepublishRequest *ds
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_REPUBLISHREQUEST]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_RepublishRequest_deleteMembers(UA_RepublishRequest *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_REPUBLISHREQUEST]);
}
@@ -22562,7 +23513,7 @@ UA_RepublishResponse_copy(const UA_RepublishResponse *src, UA_RepublishResponse
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_REPUBLISHRESPONSE]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_RepublishResponse_deleteMembers(UA_RepublishResponse *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_REPUBLISHRESPONSE]);
}
@@ -22577,6 +23528,99 @@ UA_RepublishResponse_delete(UA_RepublishResponse *p) {
UA_delete(p, &UA_TYPES[UA_TYPES_REPUBLISHRESPONSE]);
}
+/* TransferResult */
+static UA_INLINE void
+UA_TransferResult_init(UA_TransferResult *p) {
+ memset(p, 0, sizeof(UA_TransferResult));
+}
+
+static UA_INLINE UA_TransferResult *
+UA_TransferResult_new(void) {
+ return (UA_TransferResult*)UA_new(&UA_TYPES[UA_TYPES_TRANSFERRESULT]);
+}
+
+static UA_INLINE UA_StatusCode
+UA_TransferResult_copy(const UA_TransferResult *src, UA_TransferResult *dst) {
+ return UA_copy(src, dst, &UA_TYPES[UA_TYPES_TRANSFERRESULT]);
+}
+
+UA_DEPRECATED static UA_INLINE void
+UA_TransferResult_deleteMembers(UA_TransferResult *p) {
+ UA_clear(p, &UA_TYPES[UA_TYPES_TRANSFERRESULT]);
+}
+
+static UA_INLINE void
+UA_TransferResult_clear(UA_TransferResult *p) {
+ UA_clear(p, &UA_TYPES[UA_TYPES_TRANSFERRESULT]);
+}
+
+static UA_INLINE void
+UA_TransferResult_delete(UA_TransferResult *p) {
+ UA_delete(p, &UA_TYPES[UA_TYPES_TRANSFERRESULT]);
+}
+
+/* TransferSubscriptionsRequest */
+static UA_INLINE void
+UA_TransferSubscriptionsRequest_init(UA_TransferSubscriptionsRequest *p) {
+ memset(p, 0, sizeof(UA_TransferSubscriptionsRequest));
+}
+
+static UA_INLINE UA_TransferSubscriptionsRequest *
+UA_TransferSubscriptionsRequest_new(void) {
+ return (UA_TransferSubscriptionsRequest*)UA_new(&UA_TYPES[UA_TYPES_TRANSFERSUBSCRIPTIONSREQUEST]);
+}
+
+static UA_INLINE UA_StatusCode
+UA_TransferSubscriptionsRequest_copy(const UA_TransferSubscriptionsRequest *src, UA_TransferSubscriptionsRequest *dst) {
+ return UA_copy(src, dst, &UA_TYPES[UA_TYPES_TRANSFERSUBSCRIPTIONSREQUEST]);
+}
+
+UA_DEPRECATED static UA_INLINE void
+UA_TransferSubscriptionsRequest_deleteMembers(UA_TransferSubscriptionsRequest *p) {
+ UA_clear(p, &UA_TYPES[UA_TYPES_TRANSFERSUBSCRIPTIONSREQUEST]);
+}
+
+static UA_INLINE void
+UA_TransferSubscriptionsRequest_clear(UA_TransferSubscriptionsRequest *p) {
+ UA_clear(p, &UA_TYPES[UA_TYPES_TRANSFERSUBSCRIPTIONSREQUEST]);
+}
+
+static UA_INLINE void
+UA_TransferSubscriptionsRequest_delete(UA_TransferSubscriptionsRequest *p) {
+ UA_delete(p, &UA_TYPES[UA_TYPES_TRANSFERSUBSCRIPTIONSREQUEST]);
+}
+
+/* TransferSubscriptionsResponse */
+static UA_INLINE void
+UA_TransferSubscriptionsResponse_init(UA_TransferSubscriptionsResponse *p) {
+ memset(p, 0, sizeof(UA_TransferSubscriptionsResponse));
+}
+
+static UA_INLINE UA_TransferSubscriptionsResponse *
+UA_TransferSubscriptionsResponse_new(void) {
+ return (UA_TransferSubscriptionsResponse*)UA_new(&UA_TYPES[UA_TYPES_TRANSFERSUBSCRIPTIONSRESPONSE]);
+}
+
+static UA_INLINE UA_StatusCode
+UA_TransferSubscriptionsResponse_copy(const UA_TransferSubscriptionsResponse *src, UA_TransferSubscriptionsResponse *dst) {
+ return UA_copy(src, dst, &UA_TYPES[UA_TYPES_TRANSFERSUBSCRIPTIONSRESPONSE]);
+}
+
+UA_DEPRECATED static UA_INLINE void
+UA_TransferSubscriptionsResponse_deleteMembers(UA_TransferSubscriptionsResponse *p) {
+ UA_clear(p, &UA_TYPES[UA_TYPES_TRANSFERSUBSCRIPTIONSRESPONSE]);
+}
+
+static UA_INLINE void
+UA_TransferSubscriptionsResponse_clear(UA_TransferSubscriptionsResponse *p) {
+ UA_clear(p, &UA_TYPES[UA_TYPES_TRANSFERSUBSCRIPTIONSRESPONSE]);
+}
+
+static UA_INLINE void
+UA_TransferSubscriptionsResponse_delete(UA_TransferSubscriptionsResponse *p) {
+ UA_delete(p, &UA_TYPES[UA_TYPES_TRANSFERSUBSCRIPTIONSRESPONSE]);
+}
+
/* DeleteSubscriptionsRequest */
static UA_INLINE void
UA_DeleteSubscriptionsRequest_init(UA_DeleteSubscriptionsRequest *p) {
@@ -22593,7 +23637,7 @@ UA_DeleteSubscriptionsRequest_copy(const UA_DeleteSubscriptionsRequest *src, UA_
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_DELETESUBSCRIPTIONSREQUEST]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_DeleteSubscriptionsRequest_deleteMembers(UA_DeleteSubscriptionsRequest *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_DELETESUBSCRIPTIONSREQUEST]);
}
@@ -22624,7 +23668,7 @@ UA_DeleteSubscriptionsResponse_copy(const UA_DeleteSubscriptionsResponse *src, U
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_DELETESUBSCRIPTIONSRESPONSE]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_DeleteSubscriptionsResponse_deleteMembers(UA_DeleteSubscriptionsResponse *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_DELETESUBSCRIPTIONSRESPONSE]);
}
@@ -22655,7 +23699,7 @@ UA_BuildInfo_copy(const UA_BuildInfo *src, UA_BuildInfo *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_BUILDINFO]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_BuildInfo_deleteMembers(UA_BuildInfo *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_BUILDINFO]);
}
@@ -22686,7 +23730,7 @@ UA_RedundancySupport_copy(const UA_RedundancySupport *src, UA_RedundancySupport
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_REDUNDANCYSUPPORT]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_RedundancySupport_deleteMembers(UA_RedundancySupport *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_REDUNDANCYSUPPORT]);
}
@@ -22717,7 +23761,7 @@ UA_ServerState_copy(const UA_ServerState *src, UA_ServerState *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_SERVERSTATE]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_ServerState_deleteMembers(UA_ServerState *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_SERVERSTATE]);
}
@@ -22748,7 +23792,7 @@ UA_ServerDiagnosticsSummaryDataType_copy(const UA_ServerDiagnosticsSummaryDataTy
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_SERVERDIAGNOSTICSSUMMARYDATATYPE]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_ServerDiagnosticsSummaryDataType_deleteMembers(UA_ServerDiagnosticsSummaryDataType *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_SERVERDIAGNOSTICSSUMMARYDATATYPE]);
}
@@ -22779,7 +23823,7 @@ UA_ServerStatusDataType_copy(const UA_ServerStatusDataType *src, UA_ServerStatus
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_SERVERSTATUSDATATYPE]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_ServerStatusDataType_deleteMembers(UA_ServerStatusDataType *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_SERVERSTATUSDATATYPE]);
}
@@ -22810,7 +23854,7 @@ UA_Range_copy(const UA_Range *src, UA_Range *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_RANGE]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_Range_deleteMembers(UA_Range *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_RANGE]);
}
@@ -22841,7 +23885,7 @@ UA_EUInformation_copy(const UA_EUInformation *src, UA_EUInformation *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_EUINFORMATION]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_EUInformation_deleteMembers(UA_EUInformation *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_EUINFORMATION]);
}
@@ -22872,7 +23916,7 @@ UA_AxisScaleEnumeration_copy(const UA_AxisScaleEnumeration *src, UA_AxisScaleEnu
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_AXISSCALEENUMERATION]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_AxisScaleEnumeration_deleteMembers(UA_AxisScaleEnumeration *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_AXISSCALEENUMERATION]);
}
@@ -22903,7 +23947,7 @@ UA_ComplexNumberType_copy(const UA_ComplexNumberType *src, UA_ComplexNumberType
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_COMPLEXNUMBERTYPE]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_ComplexNumberType_deleteMembers(UA_ComplexNumberType *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_COMPLEXNUMBERTYPE]);
}
@@ -22934,7 +23978,7 @@ UA_DoubleComplexNumberType_copy(const UA_DoubleComplexNumberType *src, UA_Double
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_DOUBLECOMPLEXNUMBERTYPE]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_DoubleComplexNumberType_deleteMembers(UA_DoubleComplexNumberType *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_DOUBLECOMPLEXNUMBERTYPE]);
}
@@ -22965,7 +24009,7 @@ UA_AxisInformation_copy(const UA_AxisInformation *src, UA_AxisInformation *dst)
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_AXISINFORMATION]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_AxisInformation_deleteMembers(UA_AxisInformation *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_AXISINFORMATION]);
}
@@ -22996,7 +24040,7 @@ UA_XVType_copy(const UA_XVType *src, UA_XVType *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_XVTYPE]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_XVType_deleteMembers(UA_XVType *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_XVTYPE]);
}
@@ -23027,7 +24071,7 @@ UA_EnumDefinition_copy(const UA_EnumDefinition *src, UA_EnumDefinition *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_ENUMDEFINITION]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_EnumDefinition_deleteMembers(UA_EnumDefinition *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_ENUMDEFINITION]);
}
@@ -23058,7 +24102,7 @@ UA_ReadEventDetails_copy(const UA_ReadEventDetails *src, UA_ReadEventDetails *ds
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_READEVENTDETAILS]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_ReadEventDetails_deleteMembers(UA_ReadEventDetails *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_READEVENTDETAILS]);
}
@@ -23089,7 +24133,7 @@ UA_ReadProcessedDetails_copy(const UA_ReadProcessedDetails *src, UA_ReadProcesse
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_READPROCESSEDDETAILS]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_ReadProcessedDetails_deleteMembers(UA_ReadProcessedDetails *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_READPROCESSEDDETAILS]);
}
@@ -23120,7 +24164,7 @@ UA_ModificationInfo_copy(const UA_ModificationInfo *src, UA_ModificationInfo *ds
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_MODIFICATIONINFO]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_ModificationInfo_deleteMembers(UA_ModificationInfo *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_MODIFICATIONINFO]);
}
@@ -23151,7 +24195,7 @@ UA_HistoryModifiedData_copy(const UA_HistoryModifiedData *src, UA_HistoryModifie
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_HISTORYMODIFIEDDATA]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_HistoryModifiedData_deleteMembers(UA_HistoryModifiedData *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_HISTORYMODIFIEDDATA]);
}
@@ -23182,7 +24226,7 @@ UA_HistoryEvent_copy(const UA_HistoryEvent *src, UA_HistoryEvent *dst) {
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_HISTORYEVENT]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_HistoryEvent_deleteMembers(UA_HistoryEvent *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_HISTORYEVENT]);
}
@@ -23213,7 +24257,7 @@ UA_DataChangeNotification_copy(const UA_DataChangeNotification *src, UA_DataChan
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_DATACHANGENOTIFICATION]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_DataChangeNotification_deleteMembers(UA_DataChangeNotification *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_DATACHANGENOTIFICATION]);
}
@@ -23244,7 +24288,7 @@ UA_EventNotificationList_copy(const UA_EventNotificationList *src, UA_EventNotif
return UA_copy(src, dst, &UA_TYPES[UA_TYPES_EVENTNOTIFICATIONLIST]);
}
-static UA_INLINE void
+UA_DEPRECATED static UA_INLINE void
UA_EventNotificationList_deleteMembers(UA_EventNotificationList *p) {
UA_clear(p, &UA_TYPES[UA_TYPES_EVENTNOTIFICATIONLIST]);
}
@@ -23266,7 +24310,7 @@ UA_EventNotificationList_delete(UA_EventNotificationList *p) {
_UA_END_DECLS
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/include/open62541/util.h" ***********************************/
+/**** amalgamated original file "/include/open62541/util.h" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -23280,6 +24324,78 @@ _UA_END_DECLS
_UA_BEGIN_DECLS
/**
+ * Forward Declarations
+ * --------------------
+ * Opaque pointers used by the plugins. */
+
+struct UA_Server;
+typedef struct UA_Server UA_Server;
+
+struct UA_ServerConfig;
+typedef struct UA_ServerConfig UA_ServerConfig;
+
+typedef void (*UA_ServerCallback)(UA_Server *server, void *data);
+
+struct UA_Client;
+typedef struct UA_Client UA_Client;
+
+/* Timer policy to handle cycle misses */
+typedef enum {
+ UA_TIMER_HANDLE_CYCLEMISS_WITH_CURRENTTIME,
+ UA_TIMER_HANDLE_CYCLEMISS_WITH_BASETIME
+} UA_TimerPolicy;
+
+/**
+ * Key Value Map
+ * -------------
+ * Helper functions to work with configuration parameters in an array of
+ * UA_KeyValuePair. Lookup is linear. So this is for small numbers of
+ * keys. */
+
+/* Makes a copy of the value. Can reallocate the underlying array. This
+ * invalidates pointers into the previous array. If the key exists already, the
+ * value is overwritten. */
+UA_EXPORT UA_StatusCode
+UA_KeyValueMap_setQualified(UA_KeyValuePair **map, size_t *mapSize,
+ const UA_QualifiedName *key,
+ const UA_Variant *value);
+
+/* Simplified version that assumes the key is in namespace 0 */
+UA_EXPORT UA_StatusCode
+UA_KeyValueMap_set(UA_KeyValuePair **map, size_t *mapSize,
+ const char *key, const UA_Variant *value);
+
+/* Returns a pointer into underlying array or NULL if the key is not found.*/
+UA_EXPORT const UA_Variant *
+UA_KeyValueMap_getQualified(UA_KeyValuePair *map, size_t mapSize,
+ const UA_QualifiedName *key);
+
+/* Simplified version that assumes the key is in namespace 0 */
+UA_EXPORT const UA_Variant *
+UA_KeyValueMap_get(UA_KeyValuePair *map, size_t mapSize,
+ const char *key);
+
+/* Returns NULL if the value for the key is not defined or not of the right
+ * datatype and scalar/array */
+UA_EXPORT const UA_Variant *
+UA_KeyValueMap_getScalar(UA_KeyValuePair *map, size_t mapSize,
+ const char *key, const UA_DataType *type);
+
+UA_EXPORT const UA_Variant *
+UA_KeyValueMap_getArray(UA_KeyValuePair *map, size_t mapSize,
+ const char *key, const UA_DataType *type);
+
+/* Remove a single entry. To delete the entire map, use UA_Array_delete. */
+UA_EXPORT void
+UA_KeyValueMap_deleteQualified(UA_KeyValuePair **map, size_t *mapSize,
+ const UA_QualifiedName *key);
+
+/* Simplified version that assumes the key is in namespace 0 */
+UA_EXPORT void
+UA_KeyValueMap_delete(UA_KeyValuePair **map, size_t *mapSize,
+ const char *key);
+
+/**
* Endpoint URL Parser
* -------------------
* The endpoint URL parser is generally useful for the implementation of network
@@ -23332,11 +24448,11 @@ UA_readNumberWithBase(const UA_Byte *buf, size_t buflen,
UA_UInt32 *number, UA_Byte base);
#ifndef UA_MIN
-#define UA_MIN(A,B) (A > B ? B : A)
+#define UA_MIN(A, B) ((A) > (B) ? (B) : (A))
#endif
#ifndef UA_MAX
-#define UA_MAX(A,B) (A > B ? A : B)
+#define UA_MAX(A, B) ((A) > (B) ? (A) : (B))
#endif
/**
@@ -23384,7 +24500,8 @@ UA_RelativePath_parse(UA_RelativePath *rp, const UA_String str);
/**
* Convenience macros for complex types
* ------------------------------------ */
-#define UA_PRINTF_GUID_FORMAT "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x"
+#define UA_PRINTF_GUID_FORMAT "%08" PRIx32 "-%04" PRIx16 "-%04" PRIx16 \
+ "-%02" PRIx8 "%02" PRIx8 "-%02" PRIx8 "%02" PRIx8 "%02" PRIx8 "%02" PRIx8 "%02" PRIx8 "%02" PRIx8
#define UA_PRINTF_GUID_DATA(GUID) (GUID).data1, (GUID).data2, (GUID).data3, \
(GUID).data4[0], (GUID).data4[1], (GUID).data4[2], (GUID).data4[3], \
(GUID).data4[4], (GUID).data4[5], (GUID).data4[6], (GUID).data4[7]
@@ -23396,24 +24513,6 @@ UA_RelativePath_parse(UA_RelativePath *rp, const UA_String str);
* Helper functions for converting data types
* ------------------------------------------ */
-/* Converts a bytestring to the corresponding base64 representation */
-UA_DEPRECATED static UA_INLINE UA_StatusCode
-UA_ByteString_toBase64String(const UA_ByteString *byteString,
- UA_String *str) {
- return UA_ByteString_toBase64(byteString, str);
-}
-
-/* Converts a node id to the corresponding string representation.
- * It can be one of:
- * - Numeric: ns=0;i=123
- * - String: ns=0;s=Some String
- * - Guid: ns=0;g=A123456C-0ABC-1A2B-815F-687212AAEE1B
- * - ByteString: ns=0;b=AA== */
-UA_DEPRECATED static UA_INLINE UA_StatusCode
-UA_NodeId_toString(const UA_NodeId *nodeId, UA_String *nodeIdStr) {
- return UA_NodeId_print(nodeId, nodeIdStr);
-}
-
/* Compare memory in constant time to mitigate timing attacks.
* Returns true if ptr1 and ptr2 are equal for length bytes. */
static UA_INLINE UA_Boolean
@@ -23431,1608 +24530,7 @@ UA_constantTimeEqual(const void *ptr1, const void *ptr2, size_t length) {
_UA_END_DECLS
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/include/open62541/server.h" ***********************************/
-
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- *
- * Copyright 2014-2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
- * Copyright 2015-2016 (c) Sten Grüner
- * Copyright 2014-2015, 2017 (c) Florian Palm
- * Copyright 2015-2016 (c) Chris Iatrou
- * Copyright 2015-2016 (c) Oleksiy Vasylyev
- * Copyright 2016-2017 (c) Stefan Profanter, fortiss GmbH
- * Copyright 2017-2020 (c) HMS Industrial Networks AB (Author: Jonas Green)
- */
-
-
-
-_UA_BEGIN_DECLS
-
-/* Forward declarations */
-struct UA_ServerConfig;
-typedef struct UA_ServerConfig UA_ServerConfig;
-
-struct UA_Server;
-typedef struct UA_Server UA_Server;
-
-struct UA_Client;
-
-/**
- * .. _server:
- *
- * Server
- * ======
- *
- * .. include:: server_config.rst
- *
- * .. _server-lifecycle:
- *
- * Server Lifecycle
- * ---------------- */
-
-/* The method UA_Server_new is defined in server_config_default.h. So default
- * plugins outside of the core library (for logging, etc) are already available
- * during the initialization.
- *
- * UA_Server UA_EXPORT * UA_Server_new(void);
- */
-
-/* Creates a new server. Moves the config into the server with a shallow copy.
- * The config content is cleared together with the server. */
-UA_Server UA_EXPORT *
-UA_Server_newWithConfig(const UA_ServerConfig *config);
-
-void UA_EXPORT UA_Server_delete(UA_Server *server);
-
-UA_ServerConfig UA_EXPORT *
-UA_Server_getConfig(UA_Server *server);
-
-/* Runs the main loop of the server. In each iteration, this calls into the
- * networklayers to see if messages have arrived.
- *
- * @param server The server object.
- * @param running The loop is run as long as *running is true.
- * Otherwise, the server shuts down.
- * @return Returns the statuscode of the UA_Server_run_shutdown method */
-UA_StatusCode UA_EXPORT
-UA_Server_run(UA_Server *server, const volatile UA_Boolean *running);
-
-/* The prologue part of UA_Server_run (no need to use if you call
- * UA_Server_run) */
-UA_StatusCode UA_EXPORT
-UA_Server_run_startup(UA_Server *server);
-
-/* Executes a single iteration of the server's main loop.
- *
- * @param server The server object.
- * @param waitInternal Should we wait for messages in the networklayer?
- * Otherwise, the timouts for the networklayers are set to zero.
- * The default max wait time is 50millisec.
- * @return Returns how long we can wait until the next scheduled
- * callback (in ms) */
-UA_UInt16 UA_EXPORT
-UA_Server_run_iterate(UA_Server *server, UA_Boolean waitInternal);
-
-/* The epilogue part of UA_Server_run (no need to use if you call
- * UA_Server_run) */
-UA_StatusCode UA_EXPORT
-UA_Server_run_shutdown(UA_Server *server);
-
-/**
- * Timed Callbacks
- * --------------- */
-typedef void (*UA_ServerCallback)(UA_Server *server, void *data);
-
-/* Add a callback for execution at a specified time. If the indicated time lies
- * in the past, then the callback is executed at the next iteration of the
- * server's main loop.
- *
- * @param server The server object.
- * @param callback The callback that shall be added.
- * @param data Data that is forwarded to the callback.
- * @param date The timestamp for the execution time.
- * @param callbackId Set to the identifier of the repeated callback . This can
- * be used to cancel the callback later on. If the pointer is null, the
- * identifier is not set.
- * @return Upon success, UA_STATUSCODE_GOOD is returned. An error code
- * otherwise. */
-UA_StatusCode UA_EXPORT UA_THREADSAFE
-UA_Server_addTimedCallback(UA_Server *server, UA_ServerCallback callback,
- void *data, UA_DateTime date, UA_UInt64 *callbackId);
-
-/* Add a callback for cyclic repetition to the server.
- *
- * @param server The server object.
- * @param callback The callback that shall be added.
- * @param data Data that is forwarded to the callback.
- * @param interval_ms The callback shall be repeatedly executed with the given
- * interval (in ms). The interval must be positive. The first execution
- * occurs at now() + interval at the latest.
- * @param callbackId Set to the identifier of the repeated callback . This can
- * be used to cancel the callback later on. If the pointer is null, the
- * identifier is not set.
- * @return Upon success, UA_STATUSCODE_GOOD is returned. An error code
- * otherwise. */
-UA_StatusCode UA_EXPORT UA_THREADSAFE
-UA_Server_addRepeatedCallback(UA_Server *server, UA_ServerCallback callback,
- void *data, UA_Double interval_ms, UA_UInt64 *callbackId);
-
-UA_StatusCode UA_EXPORT UA_THREADSAFE
-UA_Server_changeRepeatedCallbackInterval(UA_Server *server, UA_UInt64 callbackId,
- UA_Double interval_ms);
-
-/* Remove a repeated callback. Does nothing if the callback is not found.
- *
- * @param server The server object.
- * @param callbackId The id of the callback */
-void UA_EXPORT UA_THREADSAFE
-UA_Server_removeCallback(UA_Server *server, UA_UInt64 callbackId);
-
-#define UA_Server_removeRepeatedCallback(server, callbackId) \
- UA_Server_removeCallback(server, callbackId);
-
-/**
- * Reading and Writing Node Attributes
- * -----------------------------------
- * The functions for reading and writing node attributes call the regular read
- * and write service in the background that are also used over the network.
- *
- * The following attributes cannot be read, since the local "admin" user always
- * has full rights.
- *
- * - UserWriteMask
- * - UserAccessLevel
- * - UserExecutable */
-/* Read an attribute of a node. The specialized functions below provide a more
- * concise syntax.
- *
- * @param server The server object.
- * @param item ReadValueIds contain the NodeId of the target node, the id of the
- * attribute to read and (optionally) an index range to read parts
- * of an array only. See the section on NumericRange for the format
- * used for array ranges.
- * @param timestamps Which timestamps to return for the attribute.
- * @return Returns a DataValue that contains either an error code, or a variant
- * with the attribute value and the timestamps. */
-UA_DataValue UA_EXPORT UA_THREADSAFE
-UA_Server_read(UA_Server *server, const UA_ReadValueId *item,
- UA_TimestampsToReturn timestamps);
-
-/* Don't use this function. There are typed versions for every supported
- * attribute. */
-UA_StatusCode UA_EXPORT UA_THREADSAFE
-__UA_Server_read(UA_Server *server, const UA_NodeId *nodeId,
- UA_AttributeId attributeId, void *v);
-
-static UA_INLINE UA_THREADSAFE UA_StatusCode
-UA_Server_readNodeId(UA_Server *server, const UA_NodeId nodeId,
- UA_NodeId *outNodeId) {
- return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_NODEID, outNodeId);
-}
-
-static UA_INLINE UA_THREADSAFE UA_StatusCode
-UA_Server_readNodeClass(UA_Server *server, const UA_NodeId nodeId,
- UA_NodeClass *outNodeClass) {
- return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_NODECLASS,
- outNodeClass);
-}
-
-static UA_INLINE UA_THREADSAFE UA_StatusCode
-UA_Server_readBrowseName(UA_Server *server, const UA_NodeId nodeId,
- UA_QualifiedName *outBrowseName) {
- return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_BROWSENAME,
- outBrowseName);
-}
-
-static UA_INLINE UA_THREADSAFE UA_StatusCode
-UA_Server_readDisplayName(UA_Server *server, const UA_NodeId nodeId,
- UA_LocalizedText *outDisplayName) {
- return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_DISPLAYNAME,
- outDisplayName);
-}
-
-static UA_INLINE UA_THREADSAFE UA_StatusCode
-UA_Server_readDescription(UA_Server *server, const UA_NodeId nodeId,
- UA_LocalizedText *outDescription) {
- return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_DESCRIPTION,
- outDescription);
-}
-
-static UA_INLINE UA_THREADSAFE UA_StatusCode
-UA_Server_readWriteMask(UA_Server *server, const UA_NodeId nodeId,
- UA_UInt32 *outWriteMask) {
- return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_WRITEMASK,
- outWriteMask);
-}
-
-static UA_INLINE UA_THREADSAFE UA_StatusCode
-UA_Server_readIsAbstract(UA_Server *server, const UA_NodeId nodeId,
- UA_Boolean *outIsAbstract) {
- return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_ISABSTRACT,
- outIsAbstract);
-}
-
-static UA_INLINE UA_THREADSAFE UA_StatusCode
-UA_Server_readSymmetric(UA_Server *server, const UA_NodeId nodeId,
- UA_Boolean *outSymmetric) {
- return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_SYMMETRIC,
- outSymmetric);
-}
-
-static UA_INLINE UA_THREADSAFE UA_StatusCode
-UA_Server_readInverseName(UA_Server *server, const UA_NodeId nodeId,
- UA_LocalizedText *outInverseName) {
- return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_INVERSENAME,
- outInverseName);
-}
-
-static UA_INLINE UA_THREADSAFE UA_StatusCode
-UA_Server_readContainsNoLoops(UA_Server *server, const UA_NodeId nodeId,
- UA_Boolean *outContainsNoLoops) {
- return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_CONTAINSNOLOOPS,
- outContainsNoLoops);
-}
-
-static UA_INLINE UA_THREADSAFE UA_StatusCode
-UA_Server_readEventNotifier(UA_Server *server, const UA_NodeId nodeId,
- UA_Byte *outEventNotifier) {
- return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_EVENTNOTIFIER,
- outEventNotifier);
-}
-
-static UA_INLINE UA_THREADSAFE UA_StatusCode
-UA_Server_readValue(UA_Server *server, const UA_NodeId nodeId,
- UA_Variant *outValue) {
- return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_VALUE, outValue);
-}
-
-static UA_INLINE UA_THREADSAFE UA_StatusCode
-UA_Server_readDataType(UA_Server *server, const UA_NodeId nodeId,
- UA_NodeId *outDataType) {
- return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_DATATYPE,
- outDataType);
-}
-
-static UA_INLINE UA_THREADSAFE UA_StatusCode
-UA_Server_readValueRank(UA_Server *server, const UA_NodeId nodeId,
- UA_Int32 *outValueRank) {
- return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_VALUERANK,
- outValueRank);
-}
-
-/* Returns a variant with an int32 array */
-static UA_INLINE UA_THREADSAFE UA_StatusCode
-UA_Server_readArrayDimensions(UA_Server *server, const UA_NodeId nodeId,
- UA_Variant *outArrayDimensions) {
- return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_ARRAYDIMENSIONS,
- outArrayDimensions);
-}
-
-static UA_INLINE UA_THREADSAFE UA_StatusCode
-UA_Server_readAccessLevel(UA_Server *server, const UA_NodeId nodeId,
- UA_Byte *outAccessLevel) {
- return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_ACCESSLEVEL,
- outAccessLevel);
-}
-
-static UA_INLINE UA_THREADSAFE UA_StatusCode
-UA_Server_readMinimumSamplingInterval(UA_Server *server, const UA_NodeId nodeId,
- UA_Double *outMinimumSamplingInterval) {
- return __UA_Server_read(server, &nodeId,
- UA_ATTRIBUTEID_MINIMUMSAMPLINGINTERVAL,
- outMinimumSamplingInterval);
-}
-
-static UA_INLINE UA_THREADSAFE UA_StatusCode
-UA_Server_readHistorizing(UA_Server *server, const UA_NodeId nodeId,
- UA_Boolean *outHistorizing) {
- return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_HISTORIZING,
- outHistorizing);
-}
-
-static UA_INLINE UA_THREADSAFE UA_StatusCode
-UA_Server_readExecutable(UA_Server *server, const UA_NodeId nodeId,
- UA_Boolean *outExecutable) {
- return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_EXECUTABLE,
- outExecutable);
-}
-
-/**
- * The following node attributes cannot be changed once a node has been created:
- *
- * - NodeClass
- * - NodeId
- * - Symmetric
- * - ContainsNoLoops
- *
- * The following attributes cannot be written from the server, as they are
- * specific to the different users and set by the access control callback:
- *
- * - UserWriteMask
- * - UserAccessLevel
- * - UserExecutable
- */
-
-/* Overwrite an attribute of a node. The specialized functions below provide a
- * more concise syntax.
- *
- * @param server The server object.
- * @param value WriteValues contain the NodeId of the target node, the id of the
- * attribute to overwritten, the actual value and (optionally) an
- * index range to replace parts of an array only. of an array only.
- * See the section on NumericRange for the format used for array
- * ranges.
- * @return Returns a status code. */
-UA_StatusCode UA_EXPORT UA_THREADSAFE
-UA_Server_write(UA_Server *server, const UA_WriteValue *value);
-
-/* Don't use this function. There are typed versions with no additional
- * overhead. */
-UA_StatusCode UA_EXPORT UA_THREADSAFE
-__UA_Server_write(UA_Server *server, const UA_NodeId *nodeId,
- const UA_AttributeId attributeId,
- const UA_DataType *attr_type, const void *attr);
-
-static UA_INLINE UA_THREADSAFE UA_StatusCode
-UA_Server_writeBrowseName(UA_Server *server, const UA_NodeId nodeId,
- const UA_QualifiedName browseName) {
- return __UA_Server_write(server, &nodeId, UA_ATTRIBUTEID_BROWSENAME,
- &UA_TYPES[UA_TYPES_QUALIFIEDNAME], &browseName);
-}
-
-static UA_INLINE UA_THREADSAFE UA_StatusCode
-UA_Server_writeDisplayName(UA_Server *server, const UA_NodeId nodeId,
- const UA_LocalizedText displayName) {
- return __UA_Server_write(server, &nodeId, UA_ATTRIBUTEID_DISPLAYNAME,
- &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], &displayName);
-}
-
-static UA_INLINE UA_THREADSAFE UA_StatusCode
-UA_Server_writeDescription(UA_Server *server, const UA_NodeId nodeId,
- const UA_LocalizedText description) {
- return __UA_Server_write(server, &nodeId, UA_ATTRIBUTEID_DESCRIPTION,
- &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], &description);
-}
-
-static UA_INLINE UA_THREADSAFE UA_StatusCode
-UA_Server_writeWriteMask(UA_Server *server, const UA_NodeId nodeId,
- const UA_UInt32 writeMask) {
- return __UA_Server_write(server, &nodeId, UA_ATTRIBUTEID_WRITEMASK,
- &UA_TYPES[UA_TYPES_UINT32], &writeMask);
-}
-
-static UA_INLINE UA_THREADSAFE UA_StatusCode
-UA_Server_writeIsAbstract(UA_Server *server, const UA_NodeId nodeId,
- const UA_Boolean isAbstract) {
- return __UA_Server_write(server, &nodeId, UA_ATTRIBUTEID_ISABSTRACT,
- &UA_TYPES[UA_TYPES_BOOLEAN], &isAbstract);
-}
-
-static UA_INLINE UA_THREADSAFE UA_StatusCode
-UA_Server_writeInverseName(UA_Server *server, const UA_NodeId nodeId,
- const UA_LocalizedText inverseName) {
- return __UA_Server_write(server, &nodeId, UA_ATTRIBUTEID_INVERSENAME,
- &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], &inverseName);
-}
-
-static UA_INLINE UA_THREADSAFE UA_StatusCode
-UA_Server_writeEventNotifier(UA_Server *server, const UA_NodeId nodeId,
- const UA_Byte eventNotifier) {
- return __UA_Server_write(server, &nodeId, UA_ATTRIBUTEID_EVENTNOTIFIER,
- &UA_TYPES[UA_TYPES_BYTE], &eventNotifier);
-}
-
-/**
- * Writes an UA_Variant to a variable/variableType node.
- * StatusCode is set to UA_STATUSCODE_GOOD, sourceTimestamp and
- * serverTimestamp are set to UA_DateTime_now()
- */
-static UA_INLINE UA_THREADSAFE UA_StatusCode
-UA_Server_writeValue(UA_Server *server, const UA_NodeId nodeId,
- const UA_Variant value) {
- return __UA_Server_write(server, &nodeId, UA_ATTRIBUTEID_VALUE,
- &UA_TYPES[UA_TYPES_VARIANT], &value);
-}
-
-/**
- * Writes an UA_DataValue to a variable/variableType node.
- * In contrast to UA_Server_writeValue, this functions can also write
- * sourceTimestamp, serverTimestamp and statusCode.
- */
-static UA_INLINE UA_THREADSAFE UA_StatusCode
-UA_Server_writeDataValue(UA_Server *server, const UA_NodeId nodeId,
- const UA_DataValue value) {
- return __UA_Server_write(server, &nodeId, UA_ATTRIBUTEID_VALUE,
- &UA_TYPES[UA_TYPES_DATAVALUE], &value);
-}
-
-static UA_INLINE UA_THREADSAFE UA_StatusCode
-UA_Server_writeDataType(UA_Server *server, const UA_NodeId nodeId,
- const UA_NodeId dataType) {
- return __UA_Server_write(server, &nodeId, UA_ATTRIBUTEID_DATATYPE,
- &UA_TYPES[UA_TYPES_NODEID], &dataType);
-}
-
-static UA_INLINE UA_THREADSAFE UA_StatusCode
-UA_Server_writeValueRank(UA_Server *server, const UA_NodeId nodeId,
- const UA_Int32 valueRank) {
- return __UA_Server_write(server, &nodeId, UA_ATTRIBUTEID_VALUERANK,
- &UA_TYPES[UA_TYPES_INT32], &valueRank);
-}
-
-static UA_INLINE UA_THREADSAFE UA_StatusCode
-UA_Server_writeArrayDimensions(UA_Server *server, const UA_NodeId nodeId,
- const UA_Variant arrayDimensions) {
- return __UA_Server_write(server, &nodeId, UA_ATTRIBUTEID_ARRAYDIMENSIONS,
- &UA_TYPES[UA_TYPES_VARIANT], &arrayDimensions);
-}
-
-static UA_INLINE UA_THREADSAFE UA_StatusCode
-UA_Server_writeAccessLevel(UA_Server *server, const UA_NodeId nodeId,
- const UA_Byte accessLevel) {
- return __UA_Server_write(server, &nodeId, UA_ATTRIBUTEID_ACCESSLEVEL,
- &UA_TYPES[UA_TYPES_BYTE], &accessLevel);
-}
-
-static UA_INLINE UA_THREADSAFE UA_StatusCode
-UA_Server_writeMinimumSamplingInterval(UA_Server *server, const UA_NodeId nodeId,
- const UA_Double miniumSamplingInterval) {
- return __UA_Server_write(server, &nodeId,
- UA_ATTRIBUTEID_MINIMUMSAMPLINGINTERVAL,
- &UA_TYPES[UA_TYPES_DOUBLE],
- &miniumSamplingInterval);
-}
-
-static UA_INLINE UA_THREADSAFE UA_StatusCode
-UA_Server_writeHistorizing(UA_Server *server, const UA_NodeId nodeId,
- const UA_Boolean historizing) {
- return __UA_Server_write(server, &nodeId,
- UA_ATTRIBUTEID_HISTORIZING,
- &UA_TYPES[UA_TYPES_BOOLEAN],
- &historizing);
-}
-
-static UA_INLINE UA_THREADSAFE UA_StatusCode
-UA_Server_writeExecutable(UA_Server *server, const UA_NodeId nodeId,
- const UA_Boolean executable) {
- return __UA_Server_write(server, &nodeId, UA_ATTRIBUTEID_EXECUTABLE,
- &UA_TYPES[UA_TYPES_BOOLEAN], &executable); }
-
-/**
- * Browsing
- * -------- */
-
-/* Browse the references of a particular node. See the definition of
- * BrowseDescription structure for details. */
-UA_BrowseResult UA_EXPORT UA_THREADSAFE
-UA_Server_browse(UA_Server *server, UA_UInt32 maxReferences,
- const UA_BrowseDescription *bd);
-
-UA_BrowseResult UA_EXPORT UA_THREADSAFE
-UA_Server_browseNext(UA_Server *server, UA_Boolean releaseContinuationPoint,
- const UA_ByteString *continuationPoint);
-
-/* Nonstandard version of the browse service that recurses into child nodes.
- * Possible loops (that can occur for non-hierarchical references) are handled
- * by adding every target node at most once to the results array. */
-UA_StatusCode UA_EXPORT UA_THREADSAFE
-UA_Server_browseRecursive(UA_Server *server, const UA_BrowseDescription *bd,
- size_t *resultsSize, UA_ExpandedNodeId **results);
-
-UA_BrowsePathResult UA_EXPORT UA_THREADSAFE
-UA_Server_translateBrowsePathToNodeIds(UA_Server *server,
- const UA_BrowsePath *browsePath);
-
-/* A simplified TranslateBrowsePathsToNodeIds based on the
- * SimpleAttributeOperand type (Part 4, 7.4.4.5).
- *
- * This specifies a relative path using a list of BrowseNames instead of the
- * RelativePath structure. The list of BrowseNames is equivalent to a
- * RelativePath that specifies forward references which are subtypes of the
- * HierarchicalReferences ReferenceType. All Nodes followed by the browsePath
- * shall be of the NodeClass Object or Variable. */
-UA_BrowsePathResult UA_EXPORT UA_THREADSAFE
-UA_Server_browseSimplifiedBrowsePath(UA_Server *server, const UA_NodeId origin,
- size_t browsePathSize,
- const UA_QualifiedName *browsePath);
-
-#ifndef HAVE_NODEITER_CALLBACK
-#define HAVE_NODEITER_CALLBACK
-/* Iterate over all nodes referenced by parentNodeId by calling the callback
- * function for each child node (in ifdef because GCC/CLANG handle include order
- * differently) */
-typedef UA_StatusCode
-(*UA_NodeIteratorCallback)(UA_NodeId childId, UA_Boolean isInverse,
- UA_NodeId referenceTypeId, void *handle);
-#endif
-
-UA_StatusCode UA_EXPORT UA_THREADSAFE
-UA_Server_forEachChildNodeCall(UA_Server *server, UA_NodeId parentNodeId,
- UA_NodeIteratorCallback callback, void *handle);
-
-#ifdef UA_ENABLE_DISCOVERY
-
-/**
- * Discovery
- * --------- */
-/* Register the given server instance at the discovery server.
- * This should be called periodically.
- * The semaphoreFilePath is optional. If the given file is deleted,
- * the server will automatically be unregistered. This could be
- * for example a pid file which is deleted if the server crashes.
- *
- * When the server shuts down you need to call unregister.
- *
- * @param server
- * @param client the client which is used to call the RegisterServer. It must
- * already be connected to the correct endpoint
- * @param semaphoreFilePath optional parameter pointing to semaphore file. */
-UA_StatusCode UA_EXPORT UA_THREADSAFE
-UA_Server_register_discovery(UA_Server *server, struct UA_Client *client,
- const char* semaphoreFilePath);
-
-/* Unregister the given server instance from the discovery server.
- * This should only be called when the server is shutting down.
- * @param server
- * @param client the client which is used to call the RegisterServer. It must
- * already be connected to the correct endpoint */
-UA_StatusCode UA_EXPORT UA_THREADSAFE
-UA_Server_unregister_discovery(UA_Server *server, struct UA_Client *client);
-
- /* Adds a periodic callback to register the server with the LDS (local discovery server)
- * periodically. The interval between each register call is given as second parameter.
- * It should be 10 minutes by default (= 10*60*1000).
- *
- * The delayFirstRegisterMs parameter indicates the delay for the first register call.
- * If it is 0, the first register call will be after intervalMs milliseconds,
- * otherwise the server's first register will be after delayFirstRegisterMs.
- *
- * When you manually unregister the server, you also need to cancel the
- * periodic callback, otherwise it will be automatically be registered again.
- *
- * If you call this method multiple times for the same discoveryServerUrl, the older
- * periodic callback will be removed.
- *
- * @param server
- * @param client the client which is used to call the RegisterServer.
- * It must not yet be connected and will be connected for every register call
- * to the given discoveryServerUrl.
- * @param discoveryServerUrl where this server should register itself.
- * The string will be copied internally. Therefore you can free it after calling this method.
- * @param intervalMs
- * @param delayFirstRegisterMs
- * @param periodicCallbackId */
-UA_StatusCode UA_EXPORT UA_THREADSAFE
-UA_Server_addPeriodicServerRegisterCallback(UA_Server *server, struct UA_Client *client,
- const char* discoveryServerUrl,
- UA_Double intervalMs,
- UA_Double delayFirstRegisterMs,
- UA_UInt64 *periodicCallbackId);
-
-/* Callback for RegisterServer. Data is passed from the register call */
-typedef void (*UA_Server_registerServerCallback)(const UA_RegisteredServer *registeredServer,
- void* data);
-
-/* Set the callback which is called if another server registeres or unregisters
- * with this instance. This callback is called every time the server gets a register
- * call. This especially means that for every periodic server register the callback will
- * be called.
- *
- * @param server
- * @param cb the callback
- * @param data data passed to the callback
- * @return UA_STATUSCODE_SUCCESS on success */
-void UA_EXPORT UA_THREADSAFE
-UA_Server_setRegisterServerCallback(UA_Server *server, UA_Server_registerServerCallback cb,
- void* data);
-
-#ifdef UA_ENABLE_DISCOVERY_MULTICAST
-
-/* Callback for server detected through mDNS. Data is passed from the register
- * call
- *
- * @param isServerAnnounce indicates if the server has just been detected. If
- * set to false, this means the server is shutting down.
- * @param isTxtReceived indicates if we already received the corresponding TXT
- * record with the path and caps data */
-typedef void (*UA_Server_serverOnNetworkCallback)(const UA_ServerOnNetwork *serverOnNetwork,
- UA_Boolean isServerAnnounce,
- UA_Boolean isTxtReceived, void* data);
-
-/* Set the callback which is called if another server is found through mDNS or
- * deleted. It will be called for any mDNS message from the remote server, thus
- * it may be called multiple times for the same instance. Also the SRV and TXT
- * records may arrive later, therefore for the first call the server
- * capabilities may not be set yet. If called multiple times, previous data will
- * be overwritten.
- *
- * @param server
- * @param cb the callback
- * @param data data passed to the callback
- * @return UA_STATUSCODE_SUCCESS on success */
-void UA_EXPORT UA_THREADSAFE
-UA_Server_setServerOnNetworkCallback(UA_Server *server,
- UA_Server_serverOnNetworkCallback cb,
- void* data);
-
-#endif /* UA_ENABLE_DISCOVERY_MULTICAST */
-
-#endif /* UA_ENABLE_DISCOVERY */
-
-/**
- * Information Model Callbacks
- * ---------------------------
- *
- * There are three places where a callback from an information model to
- * user-defined code can happen.
- *
- * - Custom node constructors and destructors
- * - Linking VariableNodes with an external data source
- * - MethodNode callbacks
- *
- * .. _node-lifecycle:
- *
- * Node Lifecycle: Constructors, Destructors and Node Contexts
- * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- *
- * To finalize the instantiation of a node, a (user-defined) constructor
- * callback is executed. There can be both a global constructor for all nodes
- * and node-type constructor specific to the TypeDefinition of the new node
- * (attached to an ObjectTypeNode or VariableTypeNode).
- *
- * In the hierarchy of ObjectTypes and VariableTypes, only the constructor of
- * the (lowest) type defined for the new node is executed. Note that every
- * Object and Variable can have only one ``isTypeOf`` reference. But type-nodes
- * can technically have several ``hasSubType`` references to implement multiple
- * inheritance. Issues of (multiple) inheritance in the constructor need to be
- * solved by the user.
- *
- * When a node is destroyed, the node-type destructor is called before the
- * global destructor. So the overall node lifecycle is as follows:
- *
- * 1. Global Constructor (set in the server config)
- * 2. Node-Type Constructor (for VariableType or ObjectTypes)
- * 3. (Usage-period of the Node)
- * 4. Node-Type Destructor
- * 5. Global Destructor
- *
- * The constructor and destructor callbacks can be set to ``NULL`` and are not
- * used in that case. If the node-type constructor fails, the global destructor
- * will be called before removing the node. The destructors are assumed to never
- * fail.
- *
- * Every node carries a user-context and a constructor-context pointer. The
- * user-context is used to attach custom data to a node. But the (user-defined)
- * constructors and destructors may replace the user-context pointer if they
- * wish to do so. The initial value for the constructor-context is ``NULL``.
- * When the ``AddNodes`` service is used over the network, the user-context
- * pointer of the new node is also initially set to ``NULL``. */
-
-/* To be set in the server config. */
-typedef struct {
- /* Can be NULL. May replace the nodeContext */
- UA_StatusCode (*constructor)(UA_Server *server,
- const UA_NodeId *sessionId, void *sessionContext,
- const UA_NodeId *nodeId, void **nodeContext);
-
- /* Can be NULL. The context cannot be replaced since the node is destroyed
- * immediately afterwards anyway. */
- void (*destructor)(UA_Server *server,
- const UA_NodeId *sessionId, void *sessionContext,
- const UA_NodeId *nodeId, void *nodeContext);
-
- /* Can be NULL. Called during recursive node instantiation. While mandatory
- * child nodes are automatically created if not already present, optional child
- * nodes are not. This callback can be used to define whether an optional child
- * node should be created.
- *
- * @param server The server executing the callback
- * @param sessionId The identifier of the session
- * @param sessionContext Additional data attached to the session in the
- * access control layer
- * @param sourceNodeId Source node from the type definition. If the new node
- * shall be created, it will be a copy of this node.
- * @param targetParentNodeId Parent of the potential new child node
- * @param referenceTypeId Identifies the reference type which that the parent
- * node has to the new node.
- * @return Return UA_TRUE if the child node shall be instantiatet,
- * UA_FALSE otherwise. */
- UA_Boolean (*createOptionalChild)(UA_Server *server,
- const UA_NodeId *sessionId,
- void *sessionContext,
- const UA_NodeId *sourceNodeId,
- const UA_NodeId *targetParentNodeId,
- const UA_NodeId *referenceTypeId);
-
- /* Can be NULL. Called when a node is to be copied during recursive
- * node instantiation. Allows definition of the NodeId for the new node.
- * If the callback is set to NULL or the resulting NodeId is UA_NODEID_NULL,
- * then a random NodeId will be generated.
- *
- * @param server The server executing the callback
- * @param sessionId The identifier of the session
- * @param sessionContext Additional data attached to the session in the
- * access control layer
- * @param sourceNodeId Source node of the copy operation
- * @param targetParentNodeId Parent node of the new node
- * @param referenceTypeId Identifies the reference type which that the parent
- * node has to the new node. */
- UA_StatusCode (*generateChildNodeId)(UA_Server *server,
- const UA_NodeId *sessionId, void *sessionContext,
- const UA_NodeId *sourceNodeId,
- const UA_NodeId *targetParentNodeId,
- const UA_NodeId *referenceTypeId,
- UA_NodeId *targetNodeId);
- } UA_GlobalNodeLifecycle;
-
-typedef struct {
- /* Can be NULL. May replace the nodeContext */
- UA_StatusCode (*constructor)(UA_Server *server,
- const UA_NodeId *sessionId, void *sessionContext,
- const UA_NodeId *typeNodeId, void *typeNodeContext,
- const UA_NodeId *nodeId, void **nodeContext);
-
- /* Can be NULL. May replace the nodeContext. */
- void (*destructor)(UA_Server *server,
- const UA_NodeId *sessionId, void *sessionContext,
- const UA_NodeId *typeNodeId, void *typeNodeContext,
- const UA_NodeId *nodeId, void **nodeContext);
-} UA_NodeTypeLifecycle;
-
-UA_StatusCode UA_EXPORT UA_THREADSAFE
-UA_Server_setNodeTypeLifecycle(UA_Server *server, UA_NodeId nodeId,
- UA_NodeTypeLifecycle lifecycle);
-
-UA_StatusCode UA_EXPORT UA_THREADSAFE
-UA_Server_getNodeContext(UA_Server *server, UA_NodeId nodeId,
- void **nodeContext);
-
-/* Careful! The user has to ensure that the destructor callbacks still work. */
-UA_StatusCode UA_EXPORT UA_THREADSAFE
-UA_Server_setNodeContext(UA_Server *server, UA_NodeId nodeId,
- void *nodeContext);
-
-/**
- * .. _datasource:
- *
- * Data Source Callback
- * ^^^^^^^^^^^^^^^^^^^^
- *
- * The server has a unique way of dealing with the content of variables. Instead
- * of storing a variant attached to the variable node, the node can point to a
- * function with a local data provider. Whenever the value attribute is read,
- * the function will be called and asked to provide a UA_DataValue return value
- * that contains the value content and additional timestamps.
- *
- * It is expected that the read callback is implemented. The write callback can
- * be set to a null-pointer. */
-typedef struct {
- /* Copies the data from the source into the provided value.
- *
- * !! ZERO-COPY OPERATIONS POSSIBLE !!
- * It is not required to return a copy of the actual content data. You can
- * return a pointer to memory owned by the user. Memory can be reused
- * between read callbacks of a DataSource, as the result is already encoded
- * on the network buffer between each read operation.
- *
- * To use zero-copy reads, set the value of the `value->value` Variant
- * without copying, e.g. with `UA_Variant_setScalar`. Then, also set
- * `value->value.storageType` to `UA_VARIANT_DATA_NODELETE` to prevent the
- * memory being cleaned up. Don't forget to also set `value->hasValue` to
- * true to indicate the presence of a value.
- *
- * @param server The server executing the callback
- * @param sessionId The identifier of the session
- * @param sessionContext Additional data attached to the session in the
- * access control layer
- * @param nodeId The identifier of the node being read from
- * @param nodeContext Additional data attached to the node by the user
- * @param includeSourceTimeStamp If true, then the datasource is expected to
- * set the source timestamp in the returned value
- * @param range If not null, then the datasource shall return only a
- * selection of the (nonscalar) data. Set
- * UA_STATUSCODE_BADINDEXRANGEINVALID in the value if this does not
- * apply
- * @param value The (non-null) DataValue that is returned to the client. The
- * data source sets the read data, the result status and optionally a
- * sourcetimestamp.
- * @return Returns a status code for logging. Error codes intended for the
- * original caller are set in the value. If an error is returned,
- * then no releasing of the value is done
- */
- UA_StatusCode (*read)(UA_Server *server, const UA_NodeId *sessionId,
- void *sessionContext, const UA_NodeId *nodeId,
- void *nodeContext, UA_Boolean includeSourceTimeStamp,
- const UA_NumericRange *range, UA_DataValue *value);
-
- /* Write into a data source. This method pointer can be NULL if the
- * operation is unsupported.
- *
- * @param server The server executing the callback
- * @param sessionId The identifier of the session
- * @param sessionContext Additional data attached to the session in the
- * access control layer
- * @param nodeId The identifier of the node being written to
- * @param nodeContext Additional data attached to the node by the user
- * @param range If not NULL, then the datasource shall return only a
- * selection of the (nonscalar) data. Set
- * UA_STATUSCODE_BADINDEXRANGEINVALID in the value if this does not
- * apply
- * @param value The (non-NULL) DataValue that has been written by the client.
- * The data source contains the written data, the result status and
- * optionally a sourcetimestamp
- * @return Returns a status code for logging. Error codes intended for the
- * original caller are set in the value. If an error is returned,
- * then no releasing of the value is done
- */
- UA_StatusCode (*write)(UA_Server *server, const UA_NodeId *sessionId,
- void *sessionContext, const UA_NodeId *nodeId,
- void *nodeContext, const UA_NumericRange *range,
- const UA_DataValue *value);
-} UA_DataSource;
-
-UA_StatusCode UA_EXPORT UA_THREADSAFE
-UA_Server_setVariableNode_dataSource(UA_Server *server, const UA_NodeId nodeId,
- const UA_DataSource dataSource);
-
-/**
- * .. _value-callback:
- *
- * Value Callback
- * ^^^^^^^^^^^^^^
- * Value Callbacks can be attached to variable and variable type nodes. If
- * not ``NULL``, they are called before reading and after writing respectively. */
-typedef struct {
- /* Called before the value attribute is read. It is possible to write into the
- * value attribute during onRead (using the write service). The node is
- * re-opened afterwards so that changes are considered in the following read
- * operation.
- *
- * @param handle Points to user-provided data for the callback.
- * @param nodeid The identifier of the node.
- * @param data Points to the current node value.
- * @param range Points to the numeric range the client wants to read from
- * (or NULL). */
- void (*onRead)(UA_Server *server, const UA_NodeId *sessionId,
- void *sessionContext, const UA_NodeId *nodeid,
- void *nodeContext, const UA_NumericRange *range,
- const UA_DataValue *value);
-
- /* Called after writing the value attribute. The node is re-opened after
- * writing so that the new value is visible in the callback.
- *
- * @param server The server executing the callback
- * @sessionId The identifier of the session
- * @sessionContext Additional data attached to the session
- * in the access control layer
- * @param nodeid The identifier of the node.
- * @param nodeUserContext Additional data attached to the node by
- * the user.
- * @param nodeConstructorContext Additional data attached to the node
- * by the type constructor(s).
- * @param range Points to the numeric range the client wants to write to (or
- * NULL). */
- void (*onWrite)(UA_Server *server, const UA_NodeId *sessionId,
- void *sessionContext, const UA_NodeId *nodeId,
- void *nodeContext, const UA_NumericRange *range,
- const UA_DataValue *data);
-} UA_ValueCallback;
-
-UA_StatusCode UA_EXPORT UA_THREADSAFE
-UA_Server_setVariableNode_valueCallback(UA_Server *server,
- const UA_NodeId nodeId,
- const UA_ValueCallback callback);
-
-/**
- * .. _local-monitoreditems:
- *
- * Local MonitoredItems
- * ^^^^^^^^^^^^^^^^^^^^
- *
- * MonitoredItems are used with the Subscription mechanism of OPC UA to
- * transported notifications for data changes and events. MonitoredItems can
- * also be registered locally. Notifications are then forwarded to a
- * user-defined callback instead of a remote client. */
-
-#ifdef UA_ENABLE_SUBSCRIPTIONS
-
-typedef void (*UA_Server_DataChangeNotificationCallback)
- (UA_Server *server, UA_UInt32 monitoredItemId, void *monitoredItemContext,
- const UA_NodeId *nodeId, void *nodeContext, UA_UInt32 attributeId,
- const UA_DataValue *value);
-
-typedef void (*UA_Server_EventNotificationCallback)
- (UA_Server *server, UA_UInt32 monId, void *monContext,
- size_t nEventFields, const UA_Variant *eventFields);
-
-/* Create a local MonitoredItem with a sampling interval that detects data
- * changes.
- *
- * @param server The server executing the MonitoredItem
- * @timestampsToReturn Shall timestamps be added to the value for the callback?
- * @item The parameters of the new MonitoredItem. Note that the attribute of the
- * ReadValueId (the node that is monitored) can not be
- * ``UA_ATTRIBUTEID_EVENTNOTIFIER``. A different callback type needs to be
- * registered for event notifications.
- * @monitoredItemContext A pointer that is forwarded with the callback
- * @callback The callback that is executed on detected data changes
- *
- * @return Returns a description of the created MonitoredItem. The structure
- * also contains a StatusCode (in case of an error) and the identifier of the
- * new MonitoredItem. */
-UA_MonitoredItemCreateResult UA_EXPORT UA_THREADSAFE
-UA_Server_createDataChangeMonitoredItem(UA_Server *server,
- UA_TimestampsToReturn timestampsToReturn,
- const UA_MonitoredItemCreateRequest item,
- void *monitoredItemContext,
- UA_Server_DataChangeNotificationCallback callback);
-
-/* UA_MonitoredItemCreateResult UA_EXPORT */
-/* UA_Server_createEventMonitoredItem(UA_Server *server, */
-/* UA_TimestampsToReturn timestampsToReturn, */
-/* const UA_MonitoredItemCreateRequest item, void *context, */
-/* UA_Server_EventNotificationCallback callback); */
-
-UA_StatusCode UA_EXPORT UA_THREADSAFE
-UA_Server_deleteMonitoredItem(UA_Server *server, UA_UInt32 monitoredItemId);
-
-#endif
-
-/**
- * Method Callbacks
- * ^^^^^^^^^^^^^^^^
- * Method callbacks are set to `NULL` (not executable) when a method node is
- * added over the network. In theory, it is possible to add a callback via
- * ``UA_Server_setMethodNode_callback`` within the global constructor when
- * adding methods over the network is really wanted. See the Section
- * :ref:`object-interaction` for calling methods on an object. */
-
-typedef UA_StatusCode
-(*UA_MethodCallback)(UA_Server *server, const UA_NodeId *sessionId,
- void *sessionContext, const UA_NodeId *methodId,
- void *methodContext, const UA_NodeId *objectId,
- void *objectContext, size_t inputSize,
- const UA_Variant *input, size_t outputSize,
- UA_Variant *output);
-
-#ifdef UA_ENABLE_METHODCALLS
-UA_StatusCode UA_EXPORT UA_THREADSAFE
-UA_Server_setMethodNode_callback(UA_Server *server,
- const UA_NodeId methodNodeId,
- UA_MethodCallback methodCallback);
-#endif
-
-/**
- * .. _object-interaction:
- *
- * Interacting with Objects
- * ------------------------
- * Objects in the information model are represented as ObjectNodes. Some
- * convenience functions are provided to simplify the interaction with objects.
- */
-
-/* Write an object property. The property is represented as a VariableNode with
- * a ``HasProperty`` reference from the ObjectNode. The VariableNode is
- * identified by its BrowseName. Writing the property sets the value attribute
- * of the VariableNode.
- *
- * @param server The server object
- * @param objectId The identifier of the object (node)
- * @param propertyName The name of the property
- * @param value The value to be set for the event attribute
- * @return The StatusCode for setting the event attribute */
-UA_StatusCode UA_EXPORT UA_THREADSAFE
-UA_Server_writeObjectProperty(UA_Server *server, const UA_NodeId objectId,
- const UA_QualifiedName propertyName,
- const UA_Variant value);
-
-/* Directly point to the scalar value instead of a variant */
-UA_StatusCode UA_EXPORT UA_THREADSAFE
-UA_Server_writeObjectProperty_scalar(UA_Server *server, const UA_NodeId objectId,
- const UA_QualifiedName propertyName,
- const void *value, const UA_DataType *type);
-
-/* Read an object property.
- *
- * @param server The server object
- * @param objectId The identifier of the object (node)
- * @param propertyName The name of the property
- * @param value Contains the property value after reading. Must not be NULL.
- * @return The StatusCode for setting the event attribute */
-UA_StatusCode UA_EXPORT UA_THREADSAFE
-UA_Server_readObjectProperty(UA_Server *server, const UA_NodeId objectId,
- const UA_QualifiedName propertyName,
- UA_Variant *value);
-
-#ifdef UA_ENABLE_METHODCALLS
-UA_CallMethodResult UA_EXPORT UA_THREADSAFE
-UA_Server_call(UA_Server *server, const UA_CallMethodRequest *request);
-#endif
-
-/**
- * .. _addnodes:
- *
- * Node Addition and Deletion
- * --------------------------
- * When creating dynamic node instances at runtime, chances are that you will
- * not care about the specific NodeId of the new node, as long as you can
- * reference it later. When passing numeric NodeIds with a numeric identifier 0,
- * the stack evaluates this as "select a random unassigned numeric NodeId in
- * that namespace". To find out which NodeId was actually assigned to the new
- * node, you may pass a pointer `outNewNodeId`, which will (after a successful
- * node insertion) contain the nodeId of the new node. You may also pass a
- * ``NULL`` pointer if this result is not needed.
- *
- * See the Section :ref:`node-lifecycle` on constructors and on attaching
- * user-defined data to nodes.
- *
- * The methods for node addition and deletion take mostly const arguments that
- * are not modified. When creating a node, a deep copy of the node identifier,
- * node attributes, etc. is created. Therefore, it is possible to call for
- * example ``UA_Server_addVariablenode`` with a value attribute (a
- * :ref:`variant`) pointing to a memory location on the stack. If you need
- * changes to a variable value to manifest at a specific memory location, please
- * use a :ref:`datasource` or a :ref:`value-callback`. */
-
-/* Protect against redundant definitions for server/client */
-#ifndef UA_DEFAULT_ATTRIBUTES_DEFINED
-#define UA_DEFAULT_ATTRIBUTES_DEFINED
-/* The default for variables is "BaseDataType" for the datatype, -2 for the
- * valuerank and a read-accesslevel. */
-UA_EXPORT extern const UA_VariableAttributes UA_VariableAttributes_default;
-UA_EXPORT extern const UA_VariableTypeAttributes UA_VariableTypeAttributes_default;
-/* Methods are executable by default */
-UA_EXPORT extern const UA_MethodAttributes UA_MethodAttributes_default;
-/* The remaining attribute definitions are currently all zeroed out */
-UA_EXPORT extern const UA_ObjectAttributes UA_ObjectAttributes_default;
-UA_EXPORT extern const UA_ObjectTypeAttributes UA_ObjectTypeAttributes_default;
-UA_EXPORT extern const UA_ReferenceTypeAttributes UA_ReferenceTypeAttributes_default;
-UA_EXPORT extern const UA_DataTypeAttributes UA_DataTypeAttributes_default;
-UA_EXPORT extern const UA_ViewAttributes UA_ViewAttributes_default;
-#endif
-
-/* Don't use this function. There are typed versions as inline functions. */
-UA_StatusCode UA_EXPORT UA_THREADSAFE
-__UA_Server_addNode(UA_Server *server, const UA_NodeClass nodeClass,
- const UA_NodeId *requestedNewNodeId,
- const UA_NodeId *parentNodeId,
- const UA_NodeId *referenceTypeId,
- const UA_QualifiedName browseName,
- const UA_NodeId *typeDefinition,
- const UA_NodeAttributes *attr,
- const UA_DataType *attributeType,
- void *nodeContext, UA_NodeId *outNewNodeId);
-
-static UA_INLINE UA_THREADSAFE UA_StatusCode
-UA_Server_addVariableNode(UA_Server *server, const UA_NodeId requestedNewNodeId,
- const UA_NodeId parentNodeId,
- const UA_NodeId referenceTypeId,
- const UA_QualifiedName browseName,
- const UA_NodeId typeDefinition,
- const UA_VariableAttributes attr,
- void *nodeContext, UA_NodeId *outNewNodeId) {
- return __UA_Server_addNode(server, UA_NODECLASS_VARIABLE, &requestedNewNodeId,
- &parentNodeId, &referenceTypeId, browseName,
- &typeDefinition, (const UA_NodeAttributes*)&attr,
- &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],
- nodeContext, outNewNodeId);
-}
-
-static UA_INLINE UA_THREADSAFE UA_StatusCode
-UA_Server_addVariableTypeNode(UA_Server *server,
- const UA_NodeId requestedNewNodeId,
- const UA_NodeId parentNodeId,
- const UA_NodeId referenceTypeId,
- const UA_QualifiedName browseName,
- const UA_NodeId typeDefinition,
- const UA_VariableTypeAttributes attr,
- void *nodeContext, UA_NodeId *outNewNodeId) {
- return __UA_Server_addNode(server, UA_NODECLASS_VARIABLETYPE,
- &requestedNewNodeId, &parentNodeId, &referenceTypeId,
- browseName, &typeDefinition,
- (const UA_NodeAttributes*)&attr,
- &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES],
- nodeContext, outNewNodeId);
-}
-
-static UA_INLINE UA_THREADSAFE UA_StatusCode
-UA_Server_addObjectNode(UA_Server *server, const UA_NodeId requestedNewNodeId,
- const UA_NodeId parentNodeId,
- const UA_NodeId referenceTypeId,
- const UA_QualifiedName browseName,
- const UA_NodeId typeDefinition,
- const UA_ObjectAttributes attr,
- void *nodeContext, UA_NodeId *outNewNodeId) {
- return __UA_Server_addNode(server, UA_NODECLASS_OBJECT, &requestedNewNodeId,
- &parentNodeId, &referenceTypeId, browseName,
- &typeDefinition, (const UA_NodeAttributes*)&attr,
- &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],
- nodeContext, outNewNodeId);
-}
-
-static UA_INLINE UA_THREADSAFE UA_StatusCode
-UA_Server_addObjectTypeNode(UA_Server *server, const UA_NodeId requestedNewNodeId,
- const UA_NodeId parentNodeId,
- const UA_NodeId referenceTypeId,
- const UA_QualifiedName browseName,
- const UA_ObjectTypeAttributes attr,
- void *nodeContext, UA_NodeId *outNewNodeId) {
- return __UA_Server_addNode(server, UA_NODECLASS_OBJECTTYPE, &requestedNewNodeId,
- &parentNodeId, &referenceTypeId, browseName,
- &UA_NODEID_NULL, (const UA_NodeAttributes*)&attr,
- &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],
- nodeContext, outNewNodeId);
-}
-
-static UA_INLINE UA_THREADSAFE UA_StatusCode
-UA_Server_addViewNode(UA_Server *server, const UA_NodeId requestedNewNodeId,
- const UA_NodeId parentNodeId,
- const UA_NodeId referenceTypeId,
- const UA_QualifiedName browseName,
- const UA_ViewAttributes attr,
- void *nodeContext, UA_NodeId *outNewNodeId) {
- return __UA_Server_addNode(server, UA_NODECLASS_VIEW, &requestedNewNodeId,
- &parentNodeId, &referenceTypeId, browseName,
- &UA_NODEID_NULL, (const UA_NodeAttributes*)&attr,
- &UA_TYPES[UA_TYPES_VIEWATTRIBUTES],
- nodeContext, outNewNodeId);
-}
-
-static UA_INLINE UA_THREADSAFE UA_StatusCode
-UA_Server_addReferenceTypeNode(UA_Server *server,
- const UA_NodeId requestedNewNodeId,
- const UA_NodeId parentNodeId,
- const UA_NodeId referenceTypeId,
- const UA_QualifiedName browseName,
- const UA_ReferenceTypeAttributes attr,
- void *nodeContext, UA_NodeId *outNewNodeId) {
- return __UA_Server_addNode(server, UA_NODECLASS_REFERENCETYPE,
- &requestedNewNodeId, &parentNodeId, &referenceTypeId,
- browseName, &UA_NODEID_NULL,
- (const UA_NodeAttributes*)&attr,
- &UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES],
- nodeContext, outNewNodeId);
-}
-
-static UA_INLINE UA_THREADSAFE UA_StatusCode
-UA_Server_addDataTypeNode(UA_Server *server,
- const UA_NodeId requestedNewNodeId,
- const UA_NodeId parentNodeId,
- const UA_NodeId referenceTypeId,
- const UA_QualifiedName browseName,
- const UA_DataTypeAttributes attr,
- void *nodeContext, UA_NodeId *outNewNodeId) {
- return __UA_Server_addNode(server, UA_NODECLASS_DATATYPE, &requestedNewNodeId,
- &parentNodeId, &referenceTypeId, browseName,
- &UA_NODEID_NULL, (const UA_NodeAttributes*)&attr,
- &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],
- nodeContext, outNewNodeId);
-}
-
-UA_StatusCode UA_EXPORT UA_THREADSAFE
-UA_Server_addDataSourceVariableNode(UA_Server *server,
- const UA_NodeId requestedNewNodeId,
- const UA_NodeId parentNodeId,
- const UA_NodeId referenceTypeId,
- const UA_QualifiedName browseName,
- const UA_NodeId typeDefinition,
- const UA_VariableAttributes attr,
- const UA_DataSource dataSource,
- void *nodeContext, UA_NodeId *outNewNodeId);
-
-#ifdef UA_ENABLE_METHODCALLS
-
-UA_StatusCode UA_EXPORT UA_THREADSAFE
-UA_Server_addMethodNodeEx(UA_Server *server, const UA_NodeId requestedNewNodeId,
- const UA_NodeId parentNodeId,
- const UA_NodeId referenceTypeId,
- const UA_QualifiedName browseName,
- const UA_MethodAttributes attr, UA_MethodCallback method,
- size_t inputArgumentsSize, const UA_Argument *inputArguments,
- const UA_NodeId inputArgumentsRequestedNewNodeId,
- UA_NodeId *inputArgumentsOutNewNodeId,
- size_t outputArgumentsSize, const UA_Argument *outputArguments,
- const UA_NodeId outputArgumentsRequestedNewNodeId,
- UA_NodeId *outputArgumentsOutNewNodeId,
- void *nodeContext, UA_NodeId *outNewNodeId);
-
-static UA_INLINE UA_THREADSAFE UA_StatusCode
-UA_Server_addMethodNode(UA_Server *server, const UA_NodeId requestedNewNodeId,
- const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId,
- const UA_QualifiedName browseName, const UA_MethodAttributes attr,
- UA_MethodCallback method,
- size_t inputArgumentsSize, const UA_Argument *inputArguments,
- size_t outputArgumentsSize, const UA_Argument *outputArguments,
- void *nodeContext, UA_NodeId *outNewNodeId) {
- return UA_Server_addMethodNodeEx(server, requestedNewNodeId, parentNodeId,
- referenceTypeId, browseName, attr, method,
- inputArgumentsSize, inputArguments, UA_NODEID_NULL, NULL,
- outputArgumentsSize, outputArguments, UA_NODEID_NULL, NULL,
- nodeContext, outNewNodeId);
-}
-
-#endif
-
-
-/**
- * The method pair UA_Server_addNode_begin and _finish splits the AddNodes
- * service in two parts. This is useful if the node shall be modified before
- * finish the instantiation. For example to add children with specific NodeIds.
- * Otherwise, mandatory children (e.g. of an ObjectType) are added with
- * pseudo-random unique NodeIds. Existing children are detected during the
- * _finish part via their matching BrowseName.
- *
- * The _begin method:
- * - prepares the node and adds it to the nodestore
- * - copies some unassigned attributes from the TypeDefinition node internally
- * - adds the references to the parent (and the TypeDefinition if applicable)
- * - performs type-checking of variables.
- *
- * You can add an object node without a parent if you set the parentNodeId and
- * referenceTypeId to UA_NODE_ID_NULL. Then you need to add the parent reference
- * and hasTypeDef reference yourself before calling the _finish method.
- * Not that this is only allowed for object nodes.
- *
- * The _finish method:
- * - copies mandatory children
- * - calls the node constructor(s) at the end
- * - may remove the node if it encounters an error.
- *
- * The special UA_Server_addMethodNode_finish method needs to be used for
- * method nodes, since there you need to explicitly specifiy the input
- * and output arguments which are added in the finish step (if not yet already there)
- **/
-
-/* The ``attr`` argument must have a type according to the NodeClass.
- * ``VariableAttributes`` for variables, ``ObjectAttributes`` for objects, and
- * so on. Missing attributes are taken from the TypeDefinition node if
- * applicable. */
-UA_StatusCode UA_EXPORT UA_THREADSAFE
-UA_Server_addNode_begin(UA_Server *server, const UA_NodeClass nodeClass,
- const UA_NodeId requestedNewNodeId,
- const UA_NodeId parentNodeId,
- const UA_NodeId referenceTypeId,
- const UA_QualifiedName browseName,
- const UA_NodeId typeDefinition,
- const void *attr, const UA_DataType *attributeType,
- void *nodeContext, UA_NodeId *outNewNodeId);
-
-UA_StatusCode UA_EXPORT UA_THREADSAFE
-UA_Server_addNode_finish(UA_Server *server, const UA_NodeId nodeId);
-
-#ifdef UA_ENABLE_METHODCALLS
-
-UA_StatusCode UA_EXPORT UA_THREADSAFE
-UA_Server_addMethodNode_finish(UA_Server *server, const UA_NodeId nodeId,
- UA_MethodCallback method,
- size_t inputArgumentsSize, const UA_Argument* inputArguments,
- size_t outputArgumentsSize, const UA_Argument* outputArguments);
-
-#endif
-
-/* Deletes a node and optionally all references leading to the node. */
-UA_StatusCode UA_EXPORT UA_THREADSAFE
-UA_Server_deleteNode(UA_Server *server, const UA_NodeId nodeId,
- UA_Boolean deleteReferences);
-
-/**
- * Reference Management
- * -------------------- */
-UA_StatusCode UA_EXPORT UA_THREADSAFE
-UA_Server_addReference(UA_Server *server, const UA_NodeId sourceId,
- const UA_NodeId refTypeId,
- const UA_ExpandedNodeId targetId, UA_Boolean isForward);
-
-UA_StatusCode UA_EXPORT UA_THREADSAFE
-UA_Server_deleteReference(UA_Server *server, const UA_NodeId sourceNodeId,
- const UA_NodeId referenceTypeId, UA_Boolean isForward,
- const UA_ExpandedNodeId targetNodeId,
- UA_Boolean deleteBidirectional);
-
-/**
- * .. _events:
- *
- * Events
- * ------
- * The method ``UA_Server_createEvent`` creates an event and represents it as node. The node receives a unique `EventId`
- * which is automatically added to the node.
- * The method returns a `NodeId` to the object node which represents the event through ``outNodeId``. The `NodeId` can
- * be used to set the attributes of the event. The generated `NodeId` is always numeric. ``outNodeId`` cannot be
- * ``NULL``.
- *
- * Note: In order to see an event in UAExpert, the field `Time` must be given a value!
- *
- * The method ``UA_Server_triggerEvent`` "triggers" an event by adding it to all monitored items of the specified
- * origin node and those of all its parents. Any filters specified by the monitored items are automatically applied.
- * Using this method deletes the node generated by ``UA_Server_createEvent``. The `EventId` for the new event is
- * generated automatically and is returned through ``outEventId``. ``NULL`` can be passed if the `EventId` is not
- * needed. ``deleteEventNode`` specifies whether the node representation of the event should be deleted after invoking
- * the method. This can be useful if events with the similar attributes are triggered frequently. ``UA_TRUE`` would
- * cause the node to be deleted. */
-#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
-
-/* The EventQueueOverflowEventType is defined as abstract, therefore we can not
- * create an instance of that type directly, but need to create a subtype. The
- * following is an arbitrary number which shall refer to our internal overflow
- * type. This is already posted on the OPC Foundation bug tracker under the
- * following link for clarification:
- * https://opcfoundation-onlineapplications.org/mantis/view.php?id=4206 */
-# define UA_NS0ID_SIMPLEOVERFLOWEVENTTYPE 4035
-
-/* Creates a node representation of an event
- *
- * @param server The server object
- * @param eventType The type of the event for which a node should be created
- * @param outNodeId The NodeId of the newly created node for the event
- * @return The StatusCode of the UA_Server_createEvent method */
-UA_StatusCode UA_EXPORT UA_THREADSAFE
-UA_Server_createEvent(UA_Server *server, const UA_NodeId eventType,
- UA_NodeId *outNodeId);
-
-/* Triggers a node representation of an event by applying EventFilters and
- adding the event to the appropriate queues.
- * @param server The server object
- * @param eventNodeId The NodeId of the node representation of the event which should be triggered
- * @param outEvent the EventId of the new event
- * @param deleteEventNode Specifies whether the node representation of the event should be deleted
- * @return The StatusCode of the UA_Server_triggerEvent method */
-UA_StatusCode UA_EXPORT UA_THREADSAFE
-UA_Server_triggerEvent(UA_Server *server, const UA_NodeId eventNodeId, const UA_NodeId originId,
- UA_ByteString *outEventId, const UA_Boolean deleteEventNode);
-
-#endif /* UA_ENABLE_SUBSCRIPTIONS_EVENTS */
-
-#ifdef UA_ENABLE_SUBSCRIPTIONS_ALARMS_CONDITIONS
-typedef enum UA_TwoStateVariableCallbackType {
- UA_ENTERING_ENABLEDSTATE,
- UA_ENTERING_ACKEDSTATE,
- UA_ENTERING_CONFIRMEDSTATE,
- UA_ENTERING_ACTIVESTATE
-} UA_TwoStateVariableCallbackType;
-
-/**
- * callback prototype to set user specific callbacks
- */
-typedef UA_StatusCode
-(*UA_TwoStateVariableChangeCallback)(UA_Server *server, const UA_NodeId *condition);
-
-/**
- * create condition instance. The function checks first whether the passed conditionType
- * is a subType of ConditionType. Then checks whether the condition source has HasEventSource
- * reference to its parent. If not, a HasEventSource reference will be created between condition
- * source and server object. To expose the condition in address space, a hierarchical ReferenceType
- * should be passed to create the reference to condition source. Otherwise, UA_NODEID_NULL should be
- * passed to make the condition not exposed.
- * @param server The server object
- * @param conditionId The NodeId of the requested Condition Object. UA_NODEID_NULL for random Id with NS Idx = 0.
- * @param conditionType The NodeId of the node representation of the ConditionType
- * @param conditionName The name of the condition to be created
- * @param conditionSource The NodeId of the Condition Source (Parent of the Condition)
- * @param hierarchialReferenceType The NodeId of Hierarchical ReferenceType between Condition and its source
- * @param outConditionId The NodeId of the created Condition
- * @return The StatusCode of the UA_Server_createCondition method */
-UA_StatusCode UA_EXPORT
-UA_Server_createCondition(UA_Server *server,
- const UA_NodeId conditionId, const UA_NodeId conditionType,
- UA_QualifiedName conditionName, const UA_NodeId conditionSource,
- const UA_NodeId hierarchialReferenceType, UA_NodeId *outConditionId);
-
-/**
- * set the value of condition field.
- * @param server The server object
- * @param condition The NodeId of the node representation of the Condition Instance
- * @param value Variant Value to be written to the Field
- * @param fieldName Name of the Field in which the value should be written
- * @return The StatusCode of the UA_Server_setConditionField method*/
-UA_StatusCode UA_EXPORT
-UA_Server_setConditionField(UA_Server *server,
- const UA_NodeId condition,
- const UA_Variant* value,
- const UA_QualifiedName fieldName);
-
-/**
- * set the value of property of condition field.
- * @param server The server object
- * @param condition The NodeId of the node representation of the Condition Instance
- * @param value Variant Value to be written to the Field
- * @param variableFieldName Name of the Field which has a property
- * @param variablePropertyName Name of the Field Property in which the value should be written
- * @return The StatusCode of the UA_Server_setConditionVariableFieldProperty*/
-UA_StatusCode UA_EXPORT
-UA_Server_setConditionVariableFieldProperty(UA_Server *server,
- const UA_NodeId condition,
- const UA_Variant* value,
- const UA_QualifiedName variableFieldName,
- const UA_QualifiedName variablePropertyName);
-
-/**
- * triggers an event only for an enabled condition. The condition list is updated then with the
- * last generated EventId.
- * @param server The server object
- * @param condition The NodeId of the node representation of the Condition Instance
- * @param conditionSource The NodeId of the node representation of the Condition Source
- * @param outEventId last generated EventId
- * @return The StatusCode of the UA_Server_triggerConditionEvent method*/
-UA_StatusCode UA_EXPORT
-UA_Server_triggerConditionEvent(UA_Server *server, const UA_NodeId condition,
- const UA_NodeId conditionSource, UA_ByteString *outEventId);
-
-/**
- * add an optional condition field using its name. (TODO Adding optional methods
- * is not implemented yet)
- * @param server The server object
- * @param condition The NodeId of the node representation of the Condition Instance
- * @param conditionType The NodeId of the node representation of the Condition Type
- * from which the optional field comes
- * @param fieldName Name of the optional field
- * @param outOptionalVariable The NodeId of the created field (Variable Node)
- * @return The StatusCode of the UA_Server_addConditionOptionalField method*/
-UA_StatusCode UA_EXPORT
-UA_Server_addConditionOptionalField(UA_Server *server, const UA_NodeId condition,
- const UA_NodeId conditionType, const UA_QualifiedName fieldName,
- UA_NodeId *outOptionalVariable);
-
-/**
- * Function used to set a user specific callback to TwoStateVariable Fields of
- * a condition. The callbacks will be called before triggering the events when
- * transition to true State of EnabledState/Id, AckedState/Id, ConfirmedState/Id
- * and ActiveState/Id occurs.
- * @param server The server object
- * @param condition The NodeId of the node representation of the Condition Instance
- * @param conditionSource The NodeId of the node representation of the Condition Source
- * @param removeBranch (Not Implemented yet)
- * @param callback User specific callback function
- * @param callbackType Callback function type, indicates where it should be called
- * @return The StatusCode of the UA_Server_setConditionTwoStateVariableCallback method*/
-UA_StatusCode UA_EXPORT
-UA_Server_setConditionTwoStateVariableCallback(UA_Server *server, const UA_NodeId condition,
- const UA_NodeId conditionSource, UA_Boolean removeBranch,
- UA_TwoStateVariableChangeCallback callback,
- UA_TwoStateVariableCallbackType callbackType);
-
-#endif//UA_ENABLE_SUBSCRIPTIONS_ALARMS_CONDITIONS
-
-UA_StatusCode UA_EXPORT
-UA_Server_updateCertificate(UA_Server *server,
- const UA_ByteString *oldCertificate,
- const UA_ByteString *newCertificate,
- const UA_ByteString *newPrivateKey,
- UA_Boolean closeSessions,
- UA_Boolean closeSecureChannels);
-
-/**
- * Utility Functions
- * ----------------- */
-/* Add a new namespace to the server. Returns the index of the new namespace */
-UA_UInt16 UA_EXPORT UA_THREADSAFE UA_Server_addNamespace(UA_Server *server, const char* name);
-
-/* Get namespace by name from the server. */
-UA_StatusCode UA_EXPORT UA_THREADSAFE
-UA_Server_getNamespaceByName(UA_Server *server, const UA_String namespaceUri,
- size_t* foundIndex);
-
-#ifdef UA_ENABLE_HISTORIZING
-UA_Boolean UA_EXPORT UA_THREADSAFE
-UA_Server_AccessControl_allowHistoryUpdateUpdateData(UA_Server *server,
- const UA_NodeId *sessionId, void *sessionContext,
- const UA_NodeId *nodeId,
- UA_PerformUpdateType performInsertReplace,
- const UA_DataValue *value);
-
-UA_Boolean UA_EXPORT UA_THREADSAFE
-UA_Server_AccessControl_allowHistoryUpdateDeleteRawModified(UA_Server *server,
- const UA_NodeId *sessionId, void *sessionContext,
- const UA_NodeId *nodeId,
- UA_DateTime startTimestamp,
- UA_DateTime endTimestamp,
- bool isDeleteModified);
-#endif // UA_ENABLE_HISTORIZING
-
-/**
-* .. _async-operations:
-*
-* Async Operations
-* ----------------
-* Some operations (such as reading out a sensor that needs to warm up) can take
-* quite some time. In order not to block the server during such an operation, it
-* can be "outsourced" to a worker thread.
-*
-* Take the example of a CallRequest. It is split into the individual method call
-* operations. If the method is marked as async, then the operation is put into a
-* queue where it is be retrieved by a worker. The worker returns the result when
-* ready. See the examples in ``/examples/tutorial_server_method_async.c`` for
-* the usage.
-*
-* Note that the operation can time out (see the asyncOperationTimeout setting in
-* the server config) also when it has been retrieved by the worker. */
-
-#if UA_MULTITHREADING >= 100
-
-/* Set the async flag in a method node */
-UA_StatusCode UA_EXPORT
-UA_Server_setMethodNodeAsync(UA_Server *server, const UA_NodeId id,
- UA_Boolean isAsync);
-
-typedef enum {
- UA_ASYNCOPERATIONTYPE_INVALID, /* 0, the default */
- UA_ASYNCOPERATIONTYPE_CALL
- /* UA_ASYNCOPERATIONTYPE_READ, */
- /* UA_ASYNCOPERATIONTYPE_WRITE, */
-} UA_AsyncOperationType;
-
-typedef union {
- UA_CallMethodRequest callMethodRequest;
- /* UA_ReadValueId readValueId; */
- /* UA_WriteValue writeValue; */
-} UA_AsyncOperationRequest;
-
-typedef union {
- UA_CallMethodResult callMethodResult;
- /* UA_DataValue readResult; */
- /* UA_StatusCode writeResult; */
-} UA_AsyncOperationResponse;
-
-/* Get the next async operation without blocking
- *
- * @param server The server object
- * @param type The type of the async operation
- * @param request Receives pointer to the operation
- * @param context Receives the pointer to the operation context
- * @param timeout The timestamp when the operation times out and can
- * no longer be returned to the client. The response has to
- * be set in UA_Server_setAsyncOperationResult in any case.
- * @return false if queue is empty, true else */
-UA_Boolean UA_EXPORT
-UA_Server_getAsyncOperationNonBlocking(UA_Server *server, UA_AsyncOperationType *type,
- const UA_AsyncOperationRequest **request,
- void **context, UA_DateTime *timeout);
-
-/* UA_Boolean UA_EXPORT */
-/* UA_Server_getAsyncOperationBlocking(UA_Server *server, UA_AsyncOperationType *type, */
-/* const UA_AsyncOperationRequest **request, */
-/* void **context, UA_DateTime *timeout); */
-
-/* Submit an async operation result
- *
- * @param server The server object
- * @param response Pointer to the operation result
- * @param context Pointer to the operation context */
-void UA_EXPORT
-UA_Server_setAsyncOperationResult(UA_Server *server,
- const UA_AsyncOperationResponse *response,
- void *context);
-
-/* Get the next async operation. Attention! This method is deprecated and has
- * been replaced by UA_Server_getAsyncOperationNonBlocking! */
-UA_DEPRECATED UA_Boolean UA_EXPORT
-UA_Server_getAsyncOperation(UA_Server *server, UA_AsyncOperationType *type,
- const UA_AsyncOperationRequest **request,
- void **context);
-
-#endif /* !UA_MULTITHREADING >= 100 */
-
-/**
-* Statistics
-* ----------
-*
-* Statistic counters keeping track of the current state of the stack. Counters
-* are structured per OPC UA communication layer. */
-
-typedef struct {
- UA_NetworkStatistics ns;
- UA_SecureChannelStatistics scs;
- UA_SessionStatistics ss;
-} UA_ServerStatistics;
-
-UA_ServerStatistics UA_EXPORT
-UA_Server_getStatistics(UA_Server *server);
-
-_UA_END_DECLS
-
-
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/include/open62541/plugin/log.h" ***********************************/
+/**** amalgamated original file "/include/open62541/plugin/log.h" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -25057,12 +24555,12 @@ _UA_BEGIN_DECLS
* The logger plugin is stateful and can point to custom data. So it is possible
* to keep open file handlers in the logger context.
*
- * Every log-message consists of a log-level, a log-category and a string
- * message content. The timestamp of the log-message is created within the
+ * Every log message consists of a log level, a log category and a string
+ * message content. The timestamp of the log message is created within the
* logger. */
typedef enum {
- UA_LOGLEVEL_TRACE,
+ UA_LOGLEVEL_TRACE = 0,
UA_LOGLEVEL_DEBUG,
UA_LOGLEVEL_INFO,
UA_LOGLEVEL_WARNING,
@@ -25071,7 +24569,7 @@ typedef enum {
} UA_LogLevel;
typedef enum {
- UA_LOGCATEGORY_NETWORK,
+ UA_LOGCATEGORY_NETWORK = 0,
UA_LOGCATEGORY_SECURECHANNEL,
UA_LOGCATEGORY_SESSION,
UA_LOGCATEGORY_SERVER,
@@ -25083,7 +24581,7 @@ typedef enum {
typedef struct {
/* Log a message. The message string and following varargs are formatted
* according to the rules of the printf command. Use the convenience macros
- * below that take the minimum log-level defined in ua_config.h into
+ * below that take the minimum log level defined in ua_config.h into
* account. */
void (*log)(void *logContext, UA_LogLevel level, UA_LogCategory category,
const char *msg, va_list args);
@@ -25186,7 +24684,7 @@ UA_LOG_FATAL(const UA_Logger *logger, UA_LogCategory category, const char *msg,
_UA_END_DECLS
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/include/open62541/plugin/network.h" ***********************************/
+/**** amalgamated original file "/include/open62541/plugin/network.h" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -25315,7 +24813,7 @@ struct UA_Connection {
* The network layer is part of the server config. So users can provide a custom
* implementation if the provided example does not fit their architecture. The
* network layer is invoked only from the server's main loop. So the network
- * layer does not need to be thread-safe. If the networklayer receives a
+ * layer does not need to be thread-safe. If the network layer receives a
* positive duration for blocking listening, the server's main loop will block
* until a message is received or the duration times out. */
@@ -25342,11 +24840,12 @@ struct UA_ServerNetworkLayer {
UA_ConnectionConfig localConnectionConfig;
- /* Start listening on the networklayer.
+ /* Start listening on the network layer.
*
* @param nl The network layer
* @return Returns UA_STATUSCODE_GOOD or an error code. */
- UA_StatusCode (*start)(UA_ServerNetworkLayer *nl, const UA_String *customHostname);
+ UA_StatusCode (*start)(UA_ServerNetworkLayer *nl, const UA_Logger *logger,
+ const UA_String *customHostname);
/* Listen for new and closed connections and arriving packets. Calls
* UA_Server_processBinaryMessage for the arriving packets. Closed
@@ -25387,12 +24886,12 @@ struct UA_ServerNetworkLayer {
* @param logger the logger to use */
typedef UA_Connection
(*UA_ConnectClientConnection)(UA_ConnectionConfig config, UA_String endpointUrl,
- UA_UInt32 timeout, UA_Logger *logger);
+ UA_UInt32 timeout, const UA_Logger *logger);
_UA_END_DECLS
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/include/open62541/plugin/accesscontrol.h" ***********************************/
+/**** amalgamated original file "/include/open62541/plugin/accesscontrol.h" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -25415,7 +24914,11 @@ typedef struct UA_AccessControl UA_AccessControl;
* Access Control Plugin API
* =========================
* The access control callback is used to authenticate sessions and grant access
- * rights accordingly. */
+ * rights accordingly.
+ *
+ * The ``sessionId`` and ``sessionContext`` can be both NULL. This is the case
+ * when, for example, a MonitoredItem (the underlying Subscription) is detached
+ * from its Session but continues to run. */
struct UA_AccessControl {
void *context;
@@ -25486,6 +24989,16 @@ struct UA_AccessControl {
UA_Boolean (*allowBrowseNode)(UA_Server *server, UA_AccessControl *ac,
const UA_NodeId *sessionId, void *sessionContext,
const UA_NodeId *nodeId, void *nodeContext);
+
+#ifdef UA_ENABLE_SUBSCRIPTIONS
+ /* Allow transfer of a subscription to another session. The Server shall
+ * validate that the Client of that Session is operating on behalf of the
+ * same user */
+ UA_Boolean (*allowTransferSubscription)(UA_Server *server, UA_AccessControl *ac,
+ const UA_NodeId *oldSessionId, void *oldSessionContext,
+ const UA_NodeId *newSessionId, void *newSessionContext);
+#endif
+
#ifdef UA_ENABLE_HISTORIZING
/* Allow insert,replace,update of historical data */
UA_Boolean (*allowHistoryUpdateUpdateData)(UA_Server *server, UA_AccessControl *ac,
@@ -25507,7 +25020,7 @@ struct UA_AccessControl {
_UA_END_DECLS
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/include/open62541/plugin/pki.h" ***********************************/
+/**** amalgamated original file "/include/open62541/plugin/pki.h" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -25558,7 +25071,7 @@ struct UA_CertificateVerification {
_UA_END_DECLS
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/include/open62541/plugin/securitypolicy.h" ***********************************/
+/**** amalgamated original file "/include/open62541/plugin/securitypolicy.h" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -25573,7 +25086,7 @@ _UA_END_DECLS
_UA_BEGIN_DECLS
-extern UA_EXPORT const UA_ByteString UA_SECURITY_POLICY_NONE_URI;
+extern UA_EXPORT const UA_String UA_SECURITY_POLICY_NONE_URI;
struct UA_SecurityPolicy;
typedef struct UA_SecurityPolicy UA_SecurityPolicy;
@@ -25587,19 +25100,16 @@ typedef struct {
/* Verifies the signature of the message using the provided keys in the context.
*
- * @param securityPolicy the securityPolicy the function is invoked on.
* @param channelContext the channelContext that contains the key to verify
* the supplied message with.
* @param message the message to which the signature is supposed to belong.
* @param signature the signature of the message, that should be verified. */
- UA_StatusCode (*verify)(const UA_SecurityPolicy *securityPolicy,
- void *channelContext, const UA_ByteString *message,
+ UA_StatusCode (*verify)(void *channelContext, const UA_ByteString *message,
const UA_ByteString *signature) UA_FUNC_ATTR_WARN_UNUSED_RESULT;
/* Signs the given message using this policys signing algorithm and the
* provided keys in the context.
*
- * @param securityPolicy the securityPolicy the function is invoked on.
* @param channelContext the channelContext that contains the key to sign
* the supplied message with.
* @param message the message to sign.
@@ -25607,126 +25117,94 @@ typedef struct {
* buffer needs to be allocated by the caller. The
* necessary size can be acquired with the signatureSize
* attribute of this module. */
- UA_StatusCode (*sign)(const UA_SecurityPolicy *securityPolicy,
- void *channelContext, const UA_ByteString *message,
+ UA_StatusCode (*sign)(void *channelContext, const UA_ByteString *message,
UA_ByteString *signature) UA_FUNC_ATTR_WARN_UNUSED_RESULT;
/* Gets the signature size that depends on the local (private) key.
*
- * @param securityPolicy the securityPolicy the function is invoked on.
* @param channelContext the channelContext that contains the
* certificate/key.
* @return the size of the local signature. Returns 0 if no local
* certificate was set. */
- size_t (*getLocalSignatureSize)(const UA_SecurityPolicy *securityPolicy,
- const void *channelContext);
+ size_t (*getLocalSignatureSize)(const void *channelContext);
/* Gets the signature size that depends on the remote (public) key.
*
- * @param securityPolicy the securityPolicy the function is invoked on.
* @param channelContext the context to retrieve data from.
* @return the size of the remote signature. Returns 0 if no
* remote certificate was set previousely. */
- size_t (*getRemoteSignatureSize)(const UA_SecurityPolicy *securityPolicy,
- const void *channelContext);
+ size_t (*getRemoteSignatureSize)(const void *channelContext);
/* Gets the local signing key length.
*
- * @param securityPolicy the securityPolicy the function is invoked on.
* @param channelContext the context to retrieve data from.
* @return the length of the signing key in bytes. Returns 0 if no length can be found.
*/
- size_t (*getLocalKeyLength)(const UA_SecurityPolicy *securityPolicy,
- const void *channelContext);
+ size_t (*getLocalKeyLength)(const void *channelContext);
/* Gets the local signing key length.
*
- * @param securityPolicy the securityPolicy the function is invoked on.
* @param channelContext the context to retrieve data from.
* @return the length of the signing key in bytes. Returns 0 if no length can be found.
*/
- size_t (*getRemoteKeyLength)(const UA_SecurityPolicy *securityPolicy,
- const void *channelContext);
+ size_t (*getRemoteKeyLength)(const void *channelContext);
} UA_SecurityPolicySignatureAlgorithm;
typedef struct {
UA_String uri;
- /* Encrypt the given data in place using an asymmetric algorithm and keys.
+ /* Encrypt the given data in place. For asymmetric encryption, the block
+ * size for plaintext and cypher depend on the remote key (certificate).
*
- * @param securityPolicy the securityPolicy the function is invoked on.
* @param channelContext the channelContext which contains information about
* the keys to encrypt data.
* @param data the data that is encrypted. The encrypted data will overwrite
* the data that was supplied. */
- UA_StatusCode (*encrypt)(const UA_SecurityPolicy *securityPolicy,
- void *channelContext,
+ UA_StatusCode (*encrypt)(void *channelContext,
UA_ByteString *data) UA_FUNC_ATTR_WARN_UNUSED_RESULT;
- /* Decrypts the given ciphertext in place using an asymmetric algorithm and
- * key.
+ /* Decrypts the given ciphertext in place. For asymmetric encryption, the
+ * block size for plaintext and cypher depend on the local private key.
*
- * @param securityPolicy the securityPolicy the function is invoked on.
* @param channelContext the channelContext which contains information about
* the keys needed to decrypt the message.
* @param data the data to decrypt. The decryption is done in place. */
- UA_StatusCode (*decrypt)(const UA_SecurityPolicy *securityPolicy,
- void *channelContext,
+ UA_StatusCode (*decrypt)(void *channelContext,
UA_ByteString *data) UA_FUNC_ATTR_WARN_UNUSED_RESULT;
- /* Returns the length of the key used locally to encrypt messages in bits
+ /* Returns the length of the key used to encrypt messages in bits. For
+ * asymmetric encryption the key length is for the local private key.
*
- * @param securityPolicy the securityPolicy the function is invoked on.
* @param channelContext the context to retrieve data from.
* @return the length of the local key. Returns 0 if no
* key length is known. */
- size_t (*getLocalKeyLength)(const UA_SecurityPolicy *securityPolicy,
- const void *channelContext);
+ size_t (*getLocalKeyLength)(const void *channelContext);
- /* Returns the length of the key used remotely to encrypt messages in bits
+ /* Returns the length of the key to encrypt messages in bits. Depends on the
+ * key (certificate) from the remote side.
*
- * @param securityPolicy the securityPolicy the function is invoked on.
* @param channelContext the context to retrieve data from.
* @return the length of the remote key. Returns 0 if no
* key length is known. */
- size_t (*getRemoteKeyLength)(const UA_SecurityPolicy *securityPolicy,
- const void *channelContext);
-
- /* Returns the size of encrypted blocks used by the local encryption algorithm.
- *
- * @param securityPolicy the securityPolicy the function is invoked on.
- * @param channelContext the context to retrieve data from.
- * @return the size of encrypted blocks in bytes. Returns 0 if no key length is known.
- */
- size_t (*getLocalBlockSize)(const UA_SecurityPolicy *securityPolicy,
- const void *channelContext);
+ size_t (*getRemoteKeyLength)(const void *channelContext);
- /* Returns the size of encrypted blocks used by the remote encryption algorithm.
+ /* Returns the size of encrypted blocks for sending. For asymmetric
+ * encryption this depends on the remote key (certificate). For symmetric
+ * encryption the local and remote encrypted block size are identical.
*
- * @param securityPolicy the securityPolicy the function is invoked on.
* @param channelContext the context to retrieve data from.
* @return the size of encrypted blocks in bytes. Returns 0 if no key length is known.
*/
- size_t (*getRemoteBlockSize)(const UA_SecurityPolicy *securityPolicy,
- const void *channelContext);
+ size_t (*getRemoteBlockSize)(const void *channelContext);
- /* Returns the size of plaintext blocks used by the local encryption algorithm.
+ /* Returns the size of plaintext blocks for sending. For asymmetric
+ * encryption this depends on the remote key (certificate). For symmetric
+ * encryption the local and remote plaintext block size are identical.
*
- * @param securityPolicy the securityPolicy the function is invoked on.
* @param channelContext the context to retrieve data from.
* @return the size of plaintext blocks in bytes. Returns 0 if no key length is known.
*/
- size_t (*getLocalPlainTextBlockSize)(const UA_SecurityPolicy *securityPolicy,
- const void *channelContext);
-
- /* Returns the size of plaintext blocks used by the remote encryption algorithm.
- *
- * @param securityPolicy the securityPolicy the function is invoked on.
- * @param channelContext the context to retrieve data from.
- * @return the size of plaintext blocks in bytes. Returns 0 if no key length is known.
- */
- size_t (*getRemotePlainTextBlockSize)(const UA_SecurityPolicy *securityPolicy,
- const void *channelContext);
+ size_t (*getRemotePlainTextBlockSize)(const void *channelContext);
} UA_SecurityPolicyEncryptionAlgorithm;
typedef struct {
@@ -25741,7 +25219,6 @@ typedef struct {
typedef struct {
/* Generates a thumbprint for the specified certificate.
*
- * @param securityPolicy the securityPolicy the function is invoked on.
* @param certificate the certificate to make a thumbprint of.
* @param thumbprint an output buffer for the resulting thumbprint. Always
* has the length specified in the thumbprintLength in the
@@ -25751,7 +25228,7 @@ typedef struct {
UA_ByteString *thumbprint)
UA_FUNC_ATTR_WARN_UNUSED_RESULT;
- /* Compares the supplied certificate with the certificate in the endpoit context.
+ /* Compares the supplied certificate with the certificate in the endpoint context.
*
* @param securityPolicy the policy data that contains the certificate
* to compare to.
@@ -25772,26 +25249,22 @@ typedef struct {
* For information on what parameters this function receives in what situation,
* refer to the OPC UA specification 1.03 Part6 Table 33
*
- * @param securityPolicy the securityPolicy the function is invoked on.
+ * @param policyContext The context of the policy instance
* @param secret
* @param seed
* @param out an output to write the data to. The length defines the maximum
* number of output bytes that are produced. */
- UA_StatusCode (*generateKey)(const UA_SecurityPolicy *securityPolicy,
- const UA_ByteString *secret,
+ UA_StatusCode (*generateKey)(void *policyContext, const UA_ByteString *secret,
const UA_ByteString *seed, UA_ByteString *out)
UA_FUNC_ATTR_WARN_UNUSED_RESULT;
/* Random generator for generating nonces.
*
- * @param securityPolicy the securityPolicy this function is invoked on.
- * Example: myPolicy->generateNonce(myPolicy,
- * &outBuff);
+ * @param policyContext The context of the policy instance
* @param out pointer to a buffer to store the nonce in. Needs to be
* allocated by the caller. The buffer is filled with random
* data. */
- UA_StatusCode (*generateNonce)(const UA_SecurityPolicy *securityPolicy,
- UA_ByteString *out)
+ UA_StatusCode (*generateNonce)(void *policyContext, UA_ByteString *out)
UA_FUNC_ATTR_WARN_UNUSED_RESULT;
/*
@@ -25893,7 +25366,7 @@ struct UA_SecurityPolicy {
void *policyContext;
/* The policy uri that identifies the implemented algorithms */
- UA_ByteString policyUri;
+ UA_String policyUri;
/* The local certificate is specific for each SecurityPolicy since it
* depends on the used key length. */
@@ -25917,590 +25390,66 @@ struct UA_SecurityPolicy {
void (*clear)(UA_SecurityPolicy *policy);
};
-/* Gets the number of bytes that are needed by the encryption function in
- * addition to the length of the plaintext message. This is needed, since
- * most RSA encryption methods have their own padding mechanism included.
- * This makes the encrypted message larger than the plainText, so we need to
- * have enough room in the buffer for the overhead.
- *
- * @param securityPolicy the algorithms to use.
- * @param channelContext the retrieve data from.
- * @param maxEncryptionLength the maximum number of bytes that the data to
- * encrypt can be. */
-size_t
-UA_SecurityPolicy_getRemoteAsymEncryptionBufferLengthOverhead(const UA_SecurityPolicy *securityPolicy,
- const void *channelContext,
- size_t maxEncryptionLength);
-
-/* Gets the a pointer to the context of a security policy supported by the
- * server matched by the security policy uri.
- *
- * @param server the server context.
- * @param securityPolicyUri the security policy to get the context of. */
-UA_SecurityPolicy *
-UA_SecurityPolicy_getSecurityPolicyByUri(const UA_Server *server,
- const UA_ByteString *securityPolicyUri);
-
-_UA_END_DECLS
-
-
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/include/open62541/server_pubsub.h" ***********************************/
-
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- *
- * Copyright (c) 2017-2018 Fraunhofer IOSB (Author: Andreas Ebner)
- * Copyright (c) 2019 Kalycito Infotech Private Limited
- */
-
-#ifndef UA_SERVER_PUBSUB_H
-#define UA_SERVER_PUBSUB_H
-
-
-_UA_BEGIN_DECLS
-
-#ifdef UA_ENABLE_PUBSUB
-
-/**
- * .. _pubsub:
- *
- * Publish/Subscribe
- * =================
- *
- * Work in progress!
- * This part will be a new chapter later.
- *
- * TODO: write general PubSub introduction
- *
- * The Publish/Subscribe (PubSub) extension for OPC UA enables fast and efficient
- * 1:m communication. The PubSub extension is protocol agnostic and can be used
- * with broker based protocols like MQTT and AMQP or brokerless implementations like UDP-Multicasting.
- *
- * The PubSub API uses the following scheme:
- *
- * 1. Create a configuration for the needed PubSub element.
- *
- * 2. Call the add[element] function and pass in the configuration.
- *
- * 3. The add[element] function returns the unique nodeId of the internally created element.
- *
- * Take a look on the PubSub Tutorials for mor details about the API usage.::
- *
- * +-----------+
- * | UA_Server |
- * +-----------+
- * | |
- * | |
- * | |
- * | | +----------------------+
- * | +--> UA_PubSubConnection | UA_Server_addPubSubConnection
- * | +----------------------+
- * | | |
- * | | | +----------------+
- * | | +----> UA_WriterGroup | UA_PubSubConnection_addWriterGroup
- * | | +----------------+
- * | | |
- * | | | +------------------+
- * | | +----> UA_DataSetWriter | UA_WriterGroup_addDataSetWriter +-+
- * | | +------------------+ |
- * | | |
- * | | +----------------+ | r
- * | +---------> UA_ReaderGroup | | e
- * | +----------------+ | f
- * | |
- * | +---------------------------+ |
- * +-------> UA_PubSubPublishedDataSet | UA_Server_addPublishedDataSet <-+
- * +---------------------------+
- * |
- * | +-----------------+
- * +----> UA_DataSetField | UA_PublishedDataSet_addDataSetField
- * +-----------------+
- *
- * PubSub compile flags
- * --------------------
- *
- * **UA_ENABLE_PUBSUB**
- * Enable the experimental OPC UA PubSub support. The option will include the PubSub UDP multicast plugin. Disabled by default.
- * **UA_ENABLE_PUBSUB_DELTAFRAMES**
- * The PubSub messages differentiate between keyframe (all published values contained) and deltaframe (only changed values contained) messages.
- * Deltaframe messages creation consumes some additional ressources and can be disabled with this flag. Disabled by default.
- * Compile the human-readable name of the StatusCodes into the binary. Disabled by default.
- * **UA_ENABLE_PUBSUB_INFORMATIONMODEL**
- * Enable the information model representation of the PubSub configuration. For more details take a look at the following section `PubSub Information Model Representation`. Disabled by default.
- *
- * PubSub Information Model Representation
- * ---------------------------------------
- * .. _pubsub_informationmodel:
- *
- * The complete PubSub configuration is available inside the information model.
- * The entry point is the node 'PublishSubscribe, located under the Server node.
- * The standard defines for PubSub no new Service set. The configuration can optionally
- * done over methods inside the information model. The information model representation
- * of the current PubSub configuration is generated automatically. This feature
- * can enabled/disable by changing the UA_ENABLE_PUBSUB_INFORMATIONMODEL option.
- *
- * Connections
- * -----------
- * The PubSub connections are the abstraction between the concrete transport protocol
- * and the PubSub functionality. It is possible to create multiple connections with
- * different transport protocols at runtime.
- *
- * Take a look on the PubSub Tutorials for mor details about the API usage.
- */
-
-typedef enum {
- UA_PUBSUB_PUBLISHERID_NUMERIC,
- UA_PUBSUB_PUBLISHERID_STRING
-} UA_PublisherIdType;
-
-#ifdef UA_ENABLE_PUBSUB_ETH_UADP_ETF
-typedef struct {
- UA_Int32 socketPriority;
- UA_Boolean sotxtimeEnabled;
- /* SO_TXTIME-specific additional socket config */
- UA_Int32 sotxtimeDeadlinemode;
- UA_Int32 sotxtimeReceiveerrors;
-} UA_ETFConfiguration;
-#endif
-
-typedef struct {
- UA_String name;
- UA_Boolean enabled;
- UA_PublisherIdType publisherIdType;
- union { /* std: valid types UInt or String */
- UA_UInt32 numeric;
- UA_String string;
- } publisherId;
- UA_String transportProfileUri;
- UA_Variant address;
- size_t connectionPropertiesSize;
- UA_KeyValuePair *connectionProperties;
- UA_Variant connectionTransportSettings;
-
- /* This flag is 'read only' and is set internally based on the PubSub state. */
- UA_Boolean configurationFrozen;
-
-#ifdef UA_ENABLE_PUBSUB_ETH_UADP_ETF
- /* ETF related connection configuration - Not in PubSub specfication */
- UA_ETFConfiguration etfConfiguration;
-#endif
-} UA_PubSubConnectionConfig;
-
-UA_StatusCode UA_EXPORT
-UA_Server_addPubSubConnection(UA_Server *server,
- const UA_PubSubConnectionConfig *connectionConfig,
- UA_NodeId *connectionIdentifier);
-
-/* Returns a deep copy of the config */
-UA_StatusCode UA_EXPORT
-UA_Server_getPubSubConnectionConfig(UA_Server *server,
- const UA_NodeId connection,
- UA_PubSubConnectionConfig *config);
-
-/* Remove Connection, identified by the NodeId. Deletion of Connection
- * removes all contained WriterGroups and Writers. */
-UA_StatusCode UA_EXPORT
-UA_Server_removePubSubConnection(UA_Server *server, const UA_NodeId connection);
-
-/**
- * PublishedDataSets
- * -----------------
- * The PublishedDataSets (PDS) are containers for the published information. The
- * PDS contain the published variables and meta informations. The metadata is
- * commonly autogenerated or given as constant argument as part of the template
- * functions. The template functions are standard defined and intended for
- * configuration tools. You should normally create a empty PDS and call the
- * functions to add new fields. */
-
-/* The UA_PUBSUB_DATASET_PUBLISHEDITEMS has currently no additional members and
- * thus no dedicated config structure. */
-
-typedef enum {
- UA_PUBSUB_DATASET_PUBLISHEDITEMS,
- UA_PUBSUB_DATASET_PUBLISHEDEVENTS,
- UA_PUBSUB_DATASET_PUBLISHEDITEMS_TEMPLATE,
- UA_PUBSUB_DATASET_PUBLISHEDEVENTS_TEMPLATE,
-} UA_PublishedDataSetType;
-
-typedef struct {
- UA_DataSetMetaDataType metaData;
- size_t variablesToAddSize;
- UA_PublishedVariableDataType *variablesToAdd;
-} UA_PublishedDataItemsTemplateConfig;
-
-typedef struct {
- UA_NodeId eventNotfier;
- UA_ContentFilter filter;
-} UA_PublishedEventConfig;
-
-typedef struct {
- UA_DataSetMetaDataType metaData;
- UA_NodeId eventNotfier;
- size_t selectedFieldsSize;
- UA_SimpleAttributeOperand *selectedFields;
- UA_ContentFilter filter;
-} UA_PublishedEventTemplateConfig;
-
-/* Configuration structure for PublishedDataSet */
-typedef struct {
- UA_String name;
- UA_PublishedDataSetType publishedDataSetType;
- union {
- /* The UA_PUBSUB_DATASET_PUBLISHEDITEMS has currently no additional members
- * and thus no dedicated config structure.*/
- UA_PublishedDataItemsTemplateConfig itemsTemplate;
- UA_PublishedEventConfig event;
- UA_PublishedEventTemplateConfig eventTemplate;
- } config;
- /* This flag is 'read only' and is set internally based on the PubSub state. */
- UA_Boolean configurationFrozen;
-} UA_PublishedDataSetConfig;
-
-void UA_EXPORT
-UA_PublishedDataSetConfig_clear(UA_PublishedDataSetConfig *pdsConfig);
-
-typedef struct {
- UA_StatusCode addResult;
- size_t fieldAddResultsSize;
- UA_StatusCode *fieldAddResults;
- UA_ConfigurationVersionDataType configurationVersion;
-} UA_AddPublishedDataSetResult;
-
-UA_AddPublishedDataSetResult UA_EXPORT
-UA_Server_addPublishedDataSet(UA_Server *server,
- const UA_PublishedDataSetConfig *publishedDataSetConfig,
- UA_NodeId *pdsIdentifier);
-
-/* Returns a deep copy of the config */
-UA_StatusCode UA_EXPORT
-UA_Server_getPublishedDataSetConfig(UA_Server *server, const UA_NodeId pds,
- UA_PublishedDataSetConfig *config);
-
-/* Returns a deep copy of the DataSetMetaData for an specific PDS */
-UA_StatusCode UA_EXPORT
-UA_Server_getPublishedDataSetMetaData(UA_Server *server, const UA_NodeId pds,
- UA_DataSetMetaDataType *metaData);
-
-/* Remove PublishedDataSet, identified by the NodeId. Deletion of PDS removes
- * all contained and linked PDS Fields. Connected WriterGroups will be also
- * removed. */
-UA_StatusCode UA_EXPORT
-UA_Server_removePublishedDataSet(UA_Server *server, const UA_NodeId pds);
-
/**
- * DataSetFields
- * -------------
- * The description of published variables is named DataSetField. Each
- * DataSetField contains the selection of one information model node. The
- * DataSetField has additional parameters for the publishing, sampling and error
- * handling process. */
-
-typedef struct{
- UA_ConfigurationVersionDataType configurationVersion;
- UA_String fieldNameAlias;
- UA_Boolean promotedField;
- UA_PublishedVariableDataType publishParameters;
- /* non std. field */
- UA_Boolean staticValueSourceEnabled;
- UA_DataValue staticValueSource;
-} UA_DataSetVariableConfig;
-
-typedef enum {
- UA_PUBSUB_DATASETFIELD_VARIABLE,
- UA_PUBSUB_DATASETFIELD_EVENT
-} UA_DataSetFieldType;
-
-typedef struct {
- UA_DataSetFieldType dataSetFieldType;
- union {
- /* events need other config later */
- UA_DataSetVariableConfig variable;
- } field;
- /* This flag is 'read only' and is set internally based on the PubSub state. */
- UA_Boolean configurationFrozen;
-} UA_DataSetFieldConfig;
-
-void UA_EXPORT
-UA_DataSetFieldConfig_clear(UA_DataSetFieldConfig *dataSetFieldConfig);
-
-typedef struct {
- UA_StatusCode result;
- UA_ConfigurationVersionDataType configurationVersion;
-} UA_DataSetFieldResult;
-
-UA_DataSetFieldResult UA_EXPORT
-UA_Server_addDataSetField(UA_Server *server,
- const UA_NodeId publishedDataSet,
- const UA_DataSetFieldConfig *fieldConfig,
- UA_NodeId *fieldIdentifier);
-
-/* Returns a deep copy of the config */
-UA_StatusCode UA_EXPORT
-UA_Server_getDataSetFieldConfig(UA_Server *server, const UA_NodeId dsf,
- UA_DataSetFieldConfig *config);
-
-UA_DataSetFieldResult UA_EXPORT
-UA_Server_removeDataSetField(UA_Server *server, const UA_NodeId dsf);
-
-/**
- * WriterGroup
- * -----------
- * All WriterGroups are created within a PubSubConnection and automatically
- * deleted if the connection is removed. The WriterGroup is primary used as
- * container for :ref:`dsw` and network message settings. The WriterGroup can be
- * imagined as producer of the network messages. The creation of network
- * messages is controlled by parameters like the publish interval, which is e.g.
- * contained in the WriterGroup. */
-
-typedef enum {
- UA_PUBSUB_ENCODING_BINARY,
- UA_PUBSUB_ENCODING_JSON,
- UA_PUBSUB_ENCODING_UADP
-} UA_PubSubEncodingType;
-
-/**
- * WriterGroup
- * -----------
- * The message publishing can be configured for realtime requirements. The RT-levels
- * go along with different requirements. The below listed levels can be configured:
- *
- * UA_PUBSUB_RT_NONE -
- * ---> Description: Default "none-RT" Mode
- * ---> Requirements: -
- * ---> Restrictions: -
- * UA_PUBSUB_RT_DIRECT_VALUE_ACCESS (Preview - not implemented)
- * ---> Description: Normally, the latest value for each DataSetField is read out of the information model. Within this RT-mode, the
- * value source of each field configured as static pointer to an DataValue. The publish cycle won't use call the server read function.
- * ---> Requirements: All fields must be configured with a 'staticValueSource'.
- * ---> Restrictions: -
- * UA_PUBSUB_RT_FIXED_LENGTH (Preview - not implemented)
- * ---> Description: All DataSetFields have a known, non-changing length. The server will pre-generate some
- * buffers and use only memcopy operations to generate requested PubSub packages.
- * ---> Requirements: DataSetFields with variable size can't be used within this mode.
- * ---> Restrictions: The configuration must be frozen and changes are not allowed while the WriterGroup is 'Operational'.
- * UA_PUBSUB_RT_DETERMINISTIC (Preview - not implemented)
- * ---> Description: -
- * ---> Requirements: -
- * ---> Restrictions: -
- *
- * WARNING! For hard real time requirements the underlying system must be rt-capable.
- *
- */
-typedef enum {
- UA_PUBSUB_RT_NONE = 0,
- UA_PUBSUB_RT_DIRECT_VALUE_ACCESS = 1,
- UA_PUBSUB_RT_FIXED_SIZE = 2,
- UA_PUBSUB_RT_DETERMINISTIC = 4,
-} UA_PubSubRTLevel;
-
-typedef struct {
- UA_String name;
- UA_Boolean enabled;
- UA_UInt16 writerGroupId;
- UA_Duration publishingInterval;
- UA_Double keepAliveTime;
- UA_Byte priority;
- UA_MessageSecurityMode securityMode;
- UA_ExtensionObject transportSettings;
- UA_ExtensionObject messageSettings;
- size_t groupPropertiesSize;
- UA_KeyValuePair *groupProperties;
- UA_PubSubEncodingType encodingMimeType;
-
- /* non std. config parameter. maximum count of embedded DataSetMessage in
- * one NetworkMessage */
- UA_UInt16 maxEncapsulatedDataSetMessageCount;
- /* This flag is 'read only' and is set internally based on the PubSub state. */
- UA_Boolean configurationFrozen;
- /* non std. field */
- UA_PubSubRTLevel rtLevel;
-} UA_WriterGroupConfig;
-
-void UA_EXPORT
-UA_WriterGroupConfig_clear(UA_WriterGroupConfig *writerGroupConfig);
-
-/* Add a new WriterGroup to an existing Connection */
-UA_StatusCode UA_EXPORT
-UA_Server_addWriterGroup(UA_Server *server, const UA_NodeId connection,
- const UA_WriterGroupConfig *writerGroupConfig,
- UA_NodeId *writerGroupIdentifier);
-
-/* Returns a deep copy of the config */
-UA_StatusCode UA_EXPORT
-UA_Server_getWriterGroupConfig(UA_Server *server, const UA_NodeId writerGroup,
- UA_WriterGroupConfig *config);
-
-UA_StatusCode UA_EXPORT
-UA_Server_updateWriterGroupConfig(UA_Server *server, UA_NodeId writerGroupIdentifier,
- const UA_WriterGroupConfig *config);
-
-UA_StatusCode UA_EXPORT
-UA_Server_removeWriterGroup(UA_Server *server, const UA_NodeId writerGroup);
-
-UA_StatusCode UA_EXPORT
-UA_Server_freezeWriterGroupConfiguration(UA_Server *server, const UA_NodeId writerGroup);
-
-UA_StatusCode UA_EXPORT
-UA_Server_unfreezeWriterGroupConfiguration(UA_Server *server, const UA_NodeId writerGroup);
-
-UA_StatusCode UA_EXPORT
-UA_Server_setWriterGroupOperational(UA_Server *server, const UA_NodeId writerGroup);
-
-UA_StatusCode UA_EXPORT
-UA_Server_setWriterGroupDisabled(UA_Server *server, const UA_NodeId writerGroup);
-
-/**
- * .. _dsw:
- *
- * DataSetWriter
- * -------------
- * The DataSetWriters are the glue between the WriterGroups and the
- * PublishedDataSets. The DataSetWriter contain configuration parameters and
- * flags which influence the creation of DataSet messages. These messages are
- * encapsulated inside the network message. The DataSetWriter must be linked
- * with an existing PublishedDataSet and be contained within a WriterGroup. */
-
-typedef struct {
- UA_String name;
- UA_UInt16 dataSetWriterId;
- UA_DataSetFieldContentMask dataSetFieldContentMask;
- UA_UInt32 keyFrameCount;
- UA_ExtensionObject messageSettings;
- UA_ExtensionObject transportSettings;
- UA_String dataSetName;
- size_t dataSetWriterPropertiesSize;
- UA_KeyValuePair *dataSetWriterProperties;
- /* This flag is 'read only' and is set internally based on the PubSub state. */
- UA_Boolean configurationFrozen;
-} UA_DataSetWriterConfig;
-
-void UA_EXPORT
-UA_DataSetWriterConfig_clear(UA_DataSetWriterConfig *pdsConfig);
-
-/* Add a new DataSetWriter to a existing WriterGroup. The DataSetWriter must be
- * coupled with a PublishedDataSet on creation.
+ * PubSub SecurityPolicy
+ * ---------------------
*
- * Part 14, 7.1.5.2.1 defines: The link between the PublishedDataSet and
- * DataSetWriter shall be created when an instance of the DataSetWriterType is
- * created. */
-UA_StatusCode UA_EXPORT
-UA_Server_addDataSetWriter(UA_Server *server,
- const UA_NodeId writerGroup, const UA_NodeId dataSet,
- const UA_DataSetWriterConfig *dataSetWriterConfig,
- UA_NodeId *writerIdentifier);
-
-/* Returns a deep copy of the config */
-UA_StatusCode UA_EXPORT
-UA_Server_getDataSetWriterConfig(UA_Server *server, const UA_NodeId dsw,
- UA_DataSetWriterConfig *config);
-
-UA_StatusCode UA_EXPORT
-UA_Server_removeDataSetWriter(UA_Server *server, const UA_NodeId dsw);
-
-/**
- * DataSetReader
- * -------------
- * DataSetReader can receive NetworkMessages with the DataSet
- * of interest sent by the Publisher. DataSetReaders represent
- * the configuration necessary to receive and process DataSetMessages
- * on the Subscriber side */
-
-/* Parameters for PubSubSecurity */
-typedef struct {
- UA_Int32 securityMode; /* placeholder datatype 'MessageSecurityMode' */
- UA_String securityGroupId;
- size_t keyServersSize;
- UA_Int32 *keyServers;
-} UA_PubSubSecurityParameters;
-
-/* Parameters for PubSub DataSetReader Configuration */
-typedef struct {
- UA_String name;
- UA_Variant publisherId;
- UA_UInt16 writerGroupId;
- UA_UInt16 dataSetWriterId;
- UA_DataSetMetaDataType dataSetMetaData;
- UA_DataSetFieldContentMask dataSetFieldContentMask;
- UA_Double messageReceiveTimeout;
- UA_PubSubSecurityParameters securityParameters;
- UA_UadpDataSetReaderMessageDataType messageSettings;
- UA_ExtensionObject transportSettings;
- UA_TargetVariablesDataType subscribedDataSetTarget;
-} UA_DataSetReaderConfig;
-
-/* Update configuration to the dataSetReader */
-UA_StatusCode UA_EXPORT
-UA_Server_DataSetReader_updateConfig(UA_Server *server, UA_NodeId dataSetReaderIdentifier,
- UA_NodeId readerGroupIdentifier, const UA_DataSetReaderConfig *config);
-
-/* Get configuration of the dataSetReader */
-UA_StatusCode UA_EXPORT
-UA_Server_DataSetReader_getConfig(UA_Server *server, UA_NodeId dataSetReaderIdentifier,
- UA_DataSetReaderConfig *config);
-
-/* Return Status Code after creating TargetVariables in Subscriber AddressSpace
- * TargetVariables define a list of variable mappings between received DataSet fields
- * and the TargetVariables in the Subscriber AddressSpace */
-UA_StatusCode UA_EXPORT
-UA_Server_DataSetReader_createTargetVariables(UA_Server *server, UA_NodeId dataSetReaderIdentifier,
- UA_TargetVariablesDataType* targetVariables);
-
-/* To Do:Implementation of SubscribedDataSetMirrorType
- * UA_StatusCode
- * A_PubSubDataSetReader_createDataSetMirror(UA_Server *server, UA_NodeId dataSetReaderIdentifier,
- * UA_SubscribedDataSetMirrorDataType* mirror) */
-
-/**
- * ReaderGroup
- * -----------
- * All ReaderGroups are created within a PubSubConnection and automatically
- * deleted if the connection is removed. */
-
-/* ReaderGroup configuration */
-typedef struct {
- UA_String name;
- UA_PubSubSecurityParameters securityParameters;
-} UA_ReaderGroupConfig;
+ * For PubSub encryption, the message nonce is part of the (unencrypted)
+ * SecurityHeader. The nonce is required for the de- and encryption and has to
+ * be set in the channel context before de/encrypting. */
-/* Add DataSetReader to the ReaderGroup */
-UA_StatusCode UA_EXPORT
-UA_Server_addDataSetReader(UA_Server *server, UA_NodeId readerGroupIdentifier,
- const UA_DataSetReaderConfig *dataSetReaderConfig,
- UA_NodeId *readerIdentifier);
+#ifdef UA_ENABLE_PUBSUB_ENCRYPTION
+struct UA_PubSubSecurityPolicy;
+typedef struct UA_PubSubSecurityPolicy UA_PubSubSecurityPolicy;
-/* Remove DataSetReader from ReaderGroup */
-UA_StatusCode UA_EXPORT
-UA_Server_removeDataSetReader(UA_Server *server, UA_NodeId readerIdentifier);
+struct UA_PubSubSecurityPolicy {
+ UA_String policyUri; /* The policy uri that identifies the implemented
+ * algorithms */
+ UA_SecurityPolicySymmetricModule symmetricModule;
-/* To Do: Update Configuration of ReaderGroup
- * UA_StatusCode UA_EXPORT
- * UA_Server_ReaderGroup_updateConfig(UA_Server *server, UA_NodeId readerGroupIdentifier,
- * const UA_ReaderGroupConfig *config);
- */
+ /* Create the context for the WriterGroup. The keys and nonce can be NULL
+ * here. Then they have to be set before the first encryption or signing
+ * operation. */
+ UA_StatusCode
+ (*newContext)(void *policyContext,
+ const UA_ByteString *signingKey,
+ const UA_ByteString *encryptingKey,
+ const UA_ByteString *keyNonce,
+ void **wgContext);
+
+ /* Delete the WriterGroup SecurityPolicy context */
+ void (*deleteContext)(void *wgContext);
+
+ /* Set the keys and nonce for the WriterGroup. This is returned from the
+ * GetSecurityKeys method of a Security Key Service (SKS). Otherwise, set
+ * manually via out-of-band transmission of the keys. */
+ UA_StatusCode
+ (*setSecurityKeys)(void *wgContext,
+ const UA_ByteString *signingKey,
+ const UA_ByteString *encryptingKey,
+ const UA_ByteString *keyNonce)
+ UA_FUNC_ATTR_WARN_UNUSED_RESULT;
-/* Get configuraiton of ReaderGroup */
-UA_StatusCode UA_EXPORT
-UA_Server_ReaderGroup_getConfig(UA_Server *server, UA_NodeId readerGroupIdentifier,
- UA_ReaderGroupConfig *config);
+ /* The nonce is contained in the NetworkMessage SecurityHeader. Set before
+ * each en-/decryption step. */
+ UA_StatusCode
+ (*setMessageNonce)(void *wgContext,
+ const UA_ByteString *nonce)
+ UA_FUNC_ATTR_WARN_UNUSED_RESULT;
-/* Add ReaderGroup to the created connection */
-UA_StatusCode UA_EXPORT
-UA_Server_addReaderGroup(UA_Server *server, UA_NodeId connectionIdentifier,
- const UA_ReaderGroupConfig *readerGroupConfig,
- UA_NodeId *readerGroupIdentifier);
+ const UA_Logger *logger;
-/* Remove ReaderGroup from connection */
-UA_StatusCode UA_EXPORT
-UA_Server_removeReaderGroup(UA_Server *server, UA_NodeId groupIdentifier);
+ /* Deletes the dynamic content of the policy */
+ void (*clear)(UA_PubSubSecurityPolicy *policy);
+ void *policyContext;
+};
-#endif /* UA_ENABLE_PUBSUB */
+#endif
_UA_END_DECLS
-#endif /* UA_SERVER_PUBSUB_H */
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/include/open62541/plugin/pubsub.h" ***********************************/
+/**** amalgamated original file "/include/open62541/plugin/pubsub.h" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -26530,6 +25479,12 @@ _UA_BEGIN_DECLS
* with different network implementations like UDP, MQTT, AMQP. The channel
* provides basis services like send, regist, unregist, receive, close. */
+struct UA_PubSubConnectionConfig;
+typedef struct UA_PubSubConnectionConfig UA_PubSubConnectionConfig;
+
+struct UA_PubSubChannel;
+typedef struct UA_PubSubChannel UA_PubSubChannel;
+
typedef enum {
UA_PUBSUB_CHANNEL_RDY,
UA_PUBSUB_CHANNEL_PUB,
@@ -26539,8 +25494,10 @@ typedef enum {
UA_PUBSUB_CHANNEL_CLOSED
} UA_PubSubChannelState;
-struct UA_PubSubChannel;
-typedef struct UA_PubSubChannel UA_PubSubChannel;
+typedef UA_StatusCode
+(*UA_PubSubReceiveCallback)(UA_PubSubChannel *channel,
+ void *callbackContext,
+ const UA_ByteString *buffer);
/* Interface structure between network plugin and internal implementation */
struct UA_PubSubChannel {
@@ -26558,15 +25515,18 @@ struct UA_PubSubChannel {
const UA_ByteString *buf);
/* Register to an specified message source, e.g. multicast group or topic. Callback is used for mqtt. */
- UA_StatusCode (*regist)(UA_PubSubChannel * channel, UA_ExtensionObject *transportSettings,
+ UA_StatusCode (*regist)(UA_PubSubChannel *channel, UA_ExtensionObject *transportSettings,
void (*callback)(UA_ByteString *encodedBuffer, UA_ByteString *topic));
/* Remove subscription to an specified message source, e.g. multicast group or topic */
- UA_StatusCode (*unregist)(UA_PubSubChannel * channel, UA_ExtensionObject *transportSettings);
+ UA_StatusCode (*unregist)(UA_PubSubChannel *channel, UA_ExtensionObject *transportSettings);
/* Receive messages. A regist to the message source is needed before. */
- UA_StatusCode (*receive)(UA_PubSubChannel * channel, UA_ByteString *,
- UA_ExtensionObject *transportSettings, UA_UInt32 timeout);
+ UA_StatusCode (*receive)(UA_PubSubChannel *channel,
+ UA_ExtensionObject *transportSettings,
+ UA_PubSubReceiveCallback receiveCallback,
+ void *receiveCallbackContext,
+ UA_UInt32 timeout);
/* Closing the connection and implicit free of the channel structures. */
UA_StatusCode (*close)(UA_PubSubChannel *channel);
@@ -26577,47 +25537,49 @@ struct UA_PubSubChannel {
/**
* The UA_PubSubTransportLayer is used for the creation of new connections.
- * Whenever on runtime a new connection is request, the internal PubSub
- * implementation call * the 'createPubSubChannel' function. The
+ * Whenever in runtime a new connection is requested, the internal PubSub
+ * implementation calls the 'createPubSubChannel' function. The
* 'transportProfileUri' contains the standard defined transport profile
* information and is used to identify the type of connections which can be
* created by the TransportLayer. The server config contains a list of
* UA_PubSubTransportLayer. Take a look in the tutorial_pubsub_connection to get
- * informations about the TransportLayer handling. */
+ * information about the TransportLayer handling. */
typedef struct {
UA_String transportProfileUri;
UA_PubSubChannel *(*createPubSubChannel)(UA_PubSubConnectionConfig *connectionConfig);
} UA_PubSubTransportLayer;
-/**
- * The UA_ServerConfig_addPubSubTransportLayer is used to add a transport layer
- * to the server configuration. The list memory is allocated and will be freed
- * with UA_PubSubManager_delete.
- *
- * .. note:: If the UA_String transportProfileUri was dynamically allocated
- * the memory has to be freed when no longer required.
- *
- * .. note:: This has to be done before the server is started with UA_Server_run. */
-UA_StatusCode UA_EXPORT
-UA_ServerConfig_addPubSubTransportLayer(UA_ServerConfig *config,
- UA_PubSubTransportLayer *pubsubTransportLayer);
-
#endif /* UA_ENABLE_PUBSUB */
_UA_END_DECLS
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/deps/ziptree.h" ***********************************/
+/**** amalgamated original file "/deps/ziptree.h" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
- * Copyright 2018 (c) Julius Pfrommer
+ * Copyright 2018, 2021 (c) Julius Pfrommer
*/
+#include <stddef.h>
+
+#ifdef _MSC_VER
+# define ZIP_INLINE __inline
+#else
+# define ZIP_INLINE inline
+#endif
+
+/* Prevent warnings on unused static inline functions for some compilers */
+#if defined(__GNUC__) || defined(__clang__)
+# define ZIP_UNUSED __attribute__((unused))
+#else
+# define ZIP_UNUSED
+#endif
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -26631,37 +25593,70 @@ extern "C" {
* ZIP_FIND will only return the topmost of these elements in the tree.
*
* The ZIP_ENTRY definitions are to be contained in the tree entries themselves.
- * Use ZIP_PROTTYPE to define the signature of the zip tree and ZIP_IMPL (in a
- * .c compilation unit) for the method implementations.
- *
- * Zip trees are a probabilistic data structure. Entries are assigned a
- * (nonzero) rank k with probability 1/2^{k+1}. This header file does not assume
- * a specific random number generator. So the rank must be given when an entry
- * is inserted. A fast way (with a single call to a pseudo random generator) to
- * compute the rank is with ZIP_FFS32(random()). The ZIP_FFS32 returns the least
- * significant nonzero bit of a 32bit number. */
+ * Use ZIP_FUNCTIONS to define the signature of the zip tree functions. */
#define ZIP_HEAD(name, type) \
struct name { \
- struct type *zip_root; \
+ struct type *root; \
}
-#define ZIP_INIT(head) do { (head)->zip_root = NULL; } while (0)
-#define ZIP_ROOT(head) (head)->zip_root
-#define ZIP_EMPTY(head) (ZIP_ROOT(head) == NULL)
-
#define ZIP_ENTRY(type) \
struct { \
- struct type *zip_left; \
- struct type *zip_right; \
+ struct type *left; \
+ struct type *right; \
unsigned char rank; \
}
-#define ZIP_LEFT(elm, field) (elm)->field.zip_left
-#define ZIP_RIGHT(elm, field) (elm)->field.zip_right
+enum ZIP_CMP {
+ ZIP_CMP_LESS = -1,
+ ZIP_CMP_EQ = 0,
+ ZIP_CMP_MORE = 1
+};
+
+typedef enum ZIP_CMP (*zip_cmp_cb)(const void *key1, const void *key2);
+
+#define ZIP_INIT(head) do { (head)->root = NULL; } while (0)
+#define ZIP_ROOT(head) (head)->root
+#define ZIP_LEFT(elm, field) (elm)->field.left
+#define ZIP_RIGHT(elm, field) (elm)->field.right
#define ZIP_RANK(elm, field) (elm)->field.rank
-/* Shortcuts */
+/* Internal definitions. Don't use directly. */
+
+typedef void (*__zip_iter_cb)(void *elm, void *context);
+
+void *
+__ZIP_INSERT(zip_cmp_cb cmp, unsigned short fieldoffset,
+ unsigned short keyoffset, void *root, void *elm);
+
+void *
+__ZIP_REMOVE(zip_cmp_cb cmp, unsigned short fieldoffset,
+ unsigned short keyoffset, void *root, void *elm);
+
+void *
+__ZIP_FIND(zip_cmp_cb cmp, unsigned short fieldoffset,
+ unsigned short keyoffset, void *root,
+ const void *key);
+
+void
+__ZIP_ITER(unsigned short fieldoffset, __zip_iter_cb cb,
+ void *context, void *elm);
+
+void * __ZIP_MIN(unsigned short fieldoffset, void *elm);
+void * __ZIP_MAX(unsigned short fieldoffset, void *elm);
+
+/* Zip trees are a probabilistic data structure. Entries are assigned a
+ * (non-negative) rank k with probability 1/2^{k+1}. A uniformly sampled random
+ * number has to be supplied with the insert method. __ZIP_FFS32 extracts from
+ * it least significant nonzero bit of a 32bit number. This then has the correct
+ * distribution. */
+unsigned char __ZIP_FFS32(unsigned int v);
+
+/* Generate zip tree method definitions with the ZIP_FUNCTIONS macro. The
+ * comparison method "cmp" defined for every zip tree has the signature
+ *
+ * enum ZIP_CMP cmpDateTime(const keytype *a, const keytype *b); */
+
#define ZIP_INSERT(name, head, elm, rank) name##_ZIP_INSERT(head, elm, rank)
#define ZIP_REMOVE(name, head, elm) name##_ZIP_REMOVE(head, elm)
#define ZIP_FIND(name, head, key) name##_ZIP_FIND(head, key)
@@ -26669,186 +25664,50 @@ struct { \
#define ZIP_MAX(name, head) name##_ZIP_MAX(head)
#define ZIP_ITER(name, head, cb, d) name##_ZIP_ITER(head, cb, d)
-/* Zip tree method prototypes */
-#define ZIP_PROTTYPE(name, type, keytype) \
-void name##_ZIP_INSERT(struct name *head, struct type *elm, unsigned char rank); \
-void name##_ZIP_REMOVE(struct name *head, struct type *elm); \
-struct type *name##_ZIP_FIND(struct name *head, const keytype *key); \
-struct type *name##_ZIP_MIN(struct name *head); \
-struct type *name##_ZIP_MAX(struct name *head); \
-typedef void (*name##_cb)(struct type *elm, void *data); \
-void name##_ZIP_ITER(struct name *head, name##_cb cb, void *data); \
-
-/* The comparison method "cmp" defined for every zip tree has the signature
- *
- * enum ZIP_CMP cmpDateTime(const keytype *a, const keytype *b);
- *
- * The entries need an absolute ordering. So ZIP_CMP_EQ must only be returned if
- * a and b point to the same memory. (E.g. assured by unique identifiers.) */
-enum ZIP_CMP {
- ZIP_CMP_LESS = -1,
- ZIP_CMP_EQ = 0,
- ZIP_CMP_MORE = 1
-};
-
-/* Find the position of the first bit in an unsigned 32bit integer */
-#ifdef _MSC_VER
-static __inline
-#else
-static inline
-#endif
-unsigned char
-ZIP_FFS32(unsigned int v) {
- unsigned int t = 1;
- unsigned char r = 1;
- if(v == 0) return 0;
- while((v & t) == 0) {
- t = t << 1; r++;
- }
- return r;
-}
-
-/* Zip tree method implementations */
-#define ZIP_IMPL(name, type, field, keytype, keyfield, cmp) \
-static struct type * \
-__##name##_ZIP_INSERT(struct type *root, struct type *elm) { \
- if(!root) { \
- ZIP_LEFT(elm, field) = NULL; \
- ZIP_RIGHT(elm, field) = NULL; \
- return elm; \
- } \
- if((cmp)(&(elm)->keyfield, &(root)->keyfield) == ZIP_CMP_LESS) { \
- if(__##name##_ZIP_INSERT(ZIP_LEFT(root, field), elm) == elm) { \
- if(ZIP_RANK(elm, field) < ZIP_RANK(root, field)) { \
- ZIP_LEFT(root, field) = elm; \
- } else { \
- ZIP_LEFT(root, field) = ZIP_RIGHT(elm, field); \
- ZIP_RIGHT(elm, field) = root; \
- return elm; \
- } \
- } \
- } else { \
- if(__##name##_ZIP_INSERT(ZIP_RIGHT(root, field), elm) == elm) { \
- if(ZIP_RANK(elm, field) <= ZIP_RANK(root, field)) { \
- ZIP_RIGHT(root, field) = elm; \
- } else { \
- ZIP_RIGHT(root, field) = ZIP_LEFT(elm, field); \
- ZIP_LEFT(elm, field) = root; \
- return elm; \
- } \
- } \
- } \
- return root; \
-} \
- \
-void \
+#define ZIP_FUNCTIONS(name, type, field, keytype, keyfield, cmp) \
+ZIP_UNUSED static ZIP_INLINE void \
name##_ZIP_INSERT(struct name *head, struct type *elm, \
- unsigned char rank) { \
- ZIP_RANK(elm, field) = rank; \
- ZIP_ROOT(head) = __##name##_ZIP_INSERT(ZIP_ROOT(head), elm); \
-} \
- \
-static struct type * \
-__##name##ZIP(struct type *x, struct type *y) { \
- if(!x) return y; \
- if(!y) return x; \
- if(ZIP_RANK(x, field) < ZIP_RANK(y, field)) { \
- ZIP_LEFT(y, field) = __##name##ZIP(x, ZIP_LEFT(y, field)); \
- return y; \
- } \
- ZIP_RIGHT(x, field) = __##name##ZIP(ZIP_RIGHT(x, field), y); \
- return x; \
+ unsigned int r) { \
+ ZIP_RANK(elm, field) = __ZIP_FFS32(r); \
+ ZIP_ROOT(head) = (struct type*) \
+ __ZIP_INSERT(cmp, offsetof(struct type, field), \
+ offsetof(struct type, keyfield), \
+ ZIP_ROOT(head), elm); \
} \
\
-/* Modified from the original algorithm. Allow multiple */ \
-/* elements with the same key. */ \
-static struct type * \
-__##name##_ZIP_REMOVE(struct type *root, struct type *elm) { \
- if(root == elm) \
- return __##name##ZIP(ZIP_LEFT(root, field), \
- ZIP_RIGHT(root, field)); \
- enum ZIP_CMP eq = (cmp)(&(elm)->keyfield, &(root)->keyfield); \
- struct type *left = ZIP_LEFT(root, field); \
- struct type *right = ZIP_RIGHT(root, field); \
- if(eq == ZIP_CMP_LESS) { \
- if(elm == left) \
- ZIP_LEFT(root, field) = \
- __##name##ZIP(ZIP_LEFT(left, field), \
- ZIP_RIGHT(left, field)); \
- else if(left) \
- __##name##_ZIP_REMOVE(left, elm); \
- } else if(eq == ZIP_CMP_MORE) { \
- if(elm == right) \
- ZIP_RIGHT(root, field) = \
- __##name##ZIP(ZIP_LEFT(right, field), \
- ZIP_RIGHT(right, field)); \
- else if(right) \
- __##name##_ZIP_REMOVE(right, elm); \
- } else { /* ZIP_CMP_EQ, but root != elm */ \
- if(right) \
- ZIP_RIGHT(root, field) = __##name##_ZIP_REMOVE(right, elm); \
- if(left) \
- ZIP_LEFT(root, field) = __##name##_ZIP_REMOVE(left, elm); \
- } \
- return root; \
-} \
- \
-void \
+ZIP_UNUSED static ZIP_INLINE void \
name##_ZIP_REMOVE(struct name *head, struct type *elm) { \
- ZIP_ROOT(head) = __##name##_ZIP_REMOVE(ZIP_ROOT(head), elm); \
-} \
- \
-static struct type * \
-__##name##_ZIP_FIND(struct type *root, const keytype *key) { \
- if(!root) \
- return NULL; \
- enum ZIP_CMP eq = (cmp)(key, &(root)->keyfield); \
- if(eq == ZIP_CMP_EQ) { \
- return root; \
- } \
- if(eq == ZIP_CMP_LESS) { \
- return __##name##_ZIP_FIND(ZIP_LEFT(root, field), key); \
- } \
- return __##name##_ZIP_FIND(ZIP_RIGHT(root, field), key); \
+ ZIP_ROOT(head) = (struct type*) \
+ __ZIP_REMOVE(cmp, offsetof(struct type, field), \
+ offsetof(struct type, keyfield), \
+ ZIP_ROOT(head), elm); \
} \
\
-struct type * \
+ZIP_UNUSED static ZIP_INLINE struct type * \
name##_ZIP_FIND(struct name *head, const keytype *key) { \
- return __##name##_ZIP_FIND(ZIP_ROOT(head), key); \
+ return (struct type*)__ZIP_FIND(cmp, offsetof(struct type, field), \
+ offsetof(struct type, keyfield), \
+ ZIP_ROOT(head), key); \
} \
\
-struct type * \
+ZIP_UNUSED static ZIP_INLINE struct type * \
name##_ZIP_MIN(struct name *head) { \
- struct type *cur = ZIP_ROOT(head); \
- if(!cur) return NULL; \
- while(ZIP_LEFT(cur, field)) { \
- cur = ZIP_LEFT(cur, field); \
- } \
- return cur; \
+ return (struct type *)__ZIP_MIN(offsetof(struct type, field), \
+ ZIP_ROOT(head)); \
} \
\
-struct type * \
+ZIP_UNUSED static ZIP_INLINE struct type * \
name##_ZIP_MAX(struct name *head) { \
- struct type *cur = ZIP_ROOT(head); \
- if(!cur) return NULL; \
- while(ZIP_RIGHT(cur, field)) { \
- cur = ZIP_RIGHT(cur, field); \
- } \
- return cur; \
+ return (struct type *)__ZIP_MAX(offsetof(struct type, field), \
+ ZIP_ROOT(head)); \
} \
\
-static void \
-__##name##_ZIP_ITER(struct type *elm, name##_cb cb, void *data) { \
- if(!elm) \
- return; \
- __##name##_ZIP_ITER(ZIP_LEFT(elm, field), cb, data); \
- __##name##_ZIP_ITER(ZIP_RIGHT(elm, field), cb, data); \
- cb(elm, data); \
-} \
+typedef void (*name##_cb)(struct type *elm, void *context); \
\
-void \
-name##_ZIP_ITER(struct name *head, name##_cb cb, void *data) { \
- __##name##_ZIP_ITER(ZIP_ROOT(head), cb, data); \
+ZIP_UNUSED static ZIP_INLINE void \
+name##_ZIP_ITER(struct name *head, name##_cb cb, void *context) { \
+ __ZIP_ITER(offsetof(struct type, field), (__zip_iter_cb)cb, \
+ context, ZIP_ROOT(head)); \
}
#ifdef __cplusplus
@@ -26856,13 +25715,66 @@ name##_ZIP_ITER(struct name *head, name##_cb cb, void *data) { \
#endif
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/include/open62541/plugin/nodestore.h" ***********************************/
+/**** amalgamated original file "/deps/aa_tree.h" ****/
+
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Copyright 2020 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
+ */
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum aa_cmp {
+ AA_CMP_LESS = -1,
+ AA_CMP_EQ = 0,
+ AA_CMP_MORE = 1
+};
+
+struct aa_entry {
+ struct aa_entry *left;
+ struct aa_entry *right;
+ unsigned int level;
+};
+
+struct aa_head {
+ struct aa_entry *root;
+ enum aa_cmp (*cmp)(const void* a, const void* b);
+ /* Offset from the container element to the aa_entry and the key */
+ unsigned int entry_offset;
+ unsigned int key_offset;
+};
+
+/* The AA-Tree allows duplicate entries. The first matching key is returned in
+ * aa_find. */
+
+void aa_init(struct aa_head *head,
+ enum aa_cmp (*cmp)(const void*, const void*),
+ unsigned int entry_offset, unsigned int key_offset);
+void aa_insert(struct aa_head *head, void *elem);
+void aa_remove(struct aa_head *head, void *elem);
+void * aa_find(const struct aa_head *head, const void *key);
+void * aa_min(const struct aa_head *head);
+void * aa_max(const struct aa_head *head);
+void * aa_next(const struct aa_head *head, const void *elem);
+void * aa_prev(const struct aa_head *head, const void *elem);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+/**** amalgamated original file "/include/open62541/plugin/nodestore.h" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
- * Copyright 2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
+ * Copyright 2017, 2021 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
* Copyright 2017 (c) Julian Grothoff
* Copyright 2017 (c) Stefan Profanter, fortiss GmbH
*/
@@ -26879,8 +25791,9 @@ name##_ZIP_ITER(struct name *head, name##_cb cb, void *data) { \
_UA_BEGIN_DECLS
/* Forward declaration */
-#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
+#ifdef UA_ENABLE_SUBSCRIPTIONS
struct UA_MonitoredItem;
+typedef struct UA_MonitoredItem UA_MonitoredItem;
#endif
/**
@@ -26910,6 +25823,272 @@ struct UA_MonitoredItem;
* sections are purely informational so that users may have a clear mental
* model of the underlying representation.
*
+ * .. _node-lifecycle:
+ *
+ * Node Lifecycle: Constructors, Destructors and Node Contexts
+ * -----------------------------------------------------------
+ *
+ * To finalize the instantiation of a node, a (user-defined) constructor
+ * callback is executed. There can be both a global constructor for all nodes
+ * and node-type constructor specific to the TypeDefinition of the new node
+ * (attached to an ObjectTypeNode or VariableTypeNode).
+ *
+ * In the hierarchy of ObjectTypes and VariableTypes, only the constructor of
+ * the (lowest) type defined for the new node is executed. Note that every
+ * Object and Variable can have only one ``isTypeOf`` reference. But type-nodes
+ * can technically have several ``hasSubType`` references to implement multiple
+ * inheritance. Issues of (multiple) inheritance in the constructor need to be
+ * solved by the user.
+ *
+ * When a node is destroyed, the node-type destructor is called before the
+ * global destructor. So the overall node lifecycle is as follows:
+ *
+ * 1. Global Constructor (set in the server config)
+ * 2. Node-Type Constructor (for VariableType or ObjectTypes)
+ * 3. (Usage-period of the Node)
+ * 4. Node-Type Destructor
+ * 5. Global Destructor
+ *
+ * The constructor and destructor callbacks can be set to ``NULL`` and are not
+ * used in that case. If the node-type constructor fails, the global destructor
+ * will be called before removing the node. The destructors are assumed to never
+ * fail.
+ *
+ * Every node carries a user-context and a constructor-context pointer. The
+ * user-context is used to attach custom data to a node. But the (user-defined)
+ * constructors and destructors may replace the user-context pointer if they
+ * wish to do so. The initial value for the constructor-context is ``NULL``.
+ * When the ``AddNodes`` service is used over the network, the user-context
+ * pointer of the new node is also initially set to ``NULL``.
+ *
+ * Global Node Lifecycle
+ * ~~~~~~~~~~~~~~~~~~~~~~
+ * Global constructor and destructor callbacks used for every node type.
+ * To be set in the server config.
+ */
+
+typedef struct {
+ /* Can be NULL. May replace the nodeContext */
+ UA_StatusCode (*constructor)(UA_Server *server,
+ const UA_NodeId *sessionId, void *sessionContext,
+ const UA_NodeId *nodeId, void **nodeContext);
+
+ /* Can be NULL. The context cannot be replaced since the node is destroyed
+ * immediately afterwards anyway. */
+ void (*destructor)(UA_Server *server,
+ const UA_NodeId *sessionId, void *sessionContext,
+ const UA_NodeId *nodeId, void *nodeContext);
+
+ /* Can be NULL. Called during recursive node instantiation. While mandatory
+ * child nodes are automatically created if not already present, optional child
+ * nodes are not. This callback can be used to define whether an optional child
+ * node should be created.
+ *
+ * @param server The server executing the callback
+ * @param sessionId The identifier of the session
+ * @param sessionContext Additional data attached to the session in the
+ * access control layer
+ * @param sourceNodeId Source node from the type definition. If the new node
+ * shall be created, it will be a copy of this node.
+ * @param targetParentNodeId Parent of the potential new child node
+ * @param referenceTypeId Identifies the reference type which that the parent
+ * node has to the new node.
+ * @return Return UA_TRUE if the child node shall be instantiated,
+ * UA_FALSE otherwise. */
+ UA_Boolean (*createOptionalChild)(UA_Server *server,
+ const UA_NodeId *sessionId,
+ void *sessionContext,
+ const UA_NodeId *sourceNodeId,
+ const UA_NodeId *targetParentNodeId,
+ const UA_NodeId *referenceTypeId);
+
+ /* Can be NULL. Called when a node is to be copied during recursive
+ * node instantiation. Allows definition of the NodeId for the new node.
+ * If the callback is set to NULL or the resulting NodeId is UA_NODEID_NUMERIC(X,0)
+ * an unused nodeid in namespace X will be used. E.g. passing UA_NODEID_NULL will
+ * result in a NodeId in namespace 0.
+ *
+ * @param server The server executing the callback
+ * @param sessionId The identifier of the session
+ * @param sessionContext Additional data attached to the session in the
+ * access control layer
+ * @param sourceNodeId Source node of the copy operation
+ * @param targetParentNodeId Parent node of the new node
+ * @param referenceTypeId Identifies the reference type which that the parent
+ * node has to the new node. */
+ UA_StatusCode (*generateChildNodeId)(UA_Server *server,
+ const UA_NodeId *sessionId, void *sessionContext,
+ const UA_NodeId *sourceNodeId,
+ const UA_NodeId *targetParentNodeId,
+ const UA_NodeId *referenceTypeId,
+ UA_NodeId *targetNodeId);
+} UA_GlobalNodeLifecycle;
+
+/**
+ * Node Type Lifecycle
+ * ~~~~~~~~~~~~~~~~~~~
+ * Constructor and destructors for specific object and variable types. */
+typedef struct {
+ /* Can be NULL. May replace the nodeContext */
+ UA_StatusCode (*constructor)(UA_Server *server,
+ const UA_NodeId *sessionId, void *sessionContext,
+ const UA_NodeId *typeNodeId, void *typeNodeContext,
+ const UA_NodeId *nodeId, void **nodeContext);
+
+ /* Can be NULL. May replace the nodeContext. */
+ void (*destructor)(UA_Server *server,
+ const UA_NodeId *sessionId, void *sessionContext,
+ const UA_NodeId *typeNodeId, void *typeNodeContext,
+ const UA_NodeId *nodeId, void **nodeContext);
+} UA_NodeTypeLifecycle;
+
+/**
+ * ReferenceType Bitfield Representation
+ * -------------------------------------
+ * ReferenceTypes have an alternative represention as an index into a bitfield
+ * for fast comparison. The index is generated when the corresponding
+ * ReferenceTypeNode is added. By bounding the number of ReferenceTypes that can
+ * exist in the server, the bitfield can represent a set of an combination of
+ * ReferenceTypes.
+ *
+ * Every ReferenceTypeNode contains a bitfield with the set of all its subtypes.
+ * This speeds up the Browse services substantially.
+ *
+ * The following ReferenceTypes have a fixed index. The NS0 bootstrapping
+ * creates these ReferenceTypes in-order. */
+#define UA_REFERENCETYPEINDEX_REFERENCES 0
+#define UA_REFERENCETYPEINDEX_HASSUBTYPE 1
+#define UA_REFERENCETYPEINDEX_AGGREGATES 2
+#define UA_REFERENCETYPEINDEX_HIERARCHICALREFERENCES 3
+#define UA_REFERENCETYPEINDEX_NONHIERARCHICALREFERENCES 4
+#define UA_REFERENCETYPEINDEX_HASCHILD 5
+#define UA_REFERENCETYPEINDEX_ORGANIZES 6
+#define UA_REFERENCETYPEINDEX_HASEVENTSOURCE 7
+#define UA_REFERENCETYPEINDEX_HASMODELLINGRULE 8
+#define UA_REFERENCETYPEINDEX_HASENCODING 9
+#define UA_REFERENCETYPEINDEX_HASDESCRIPTION 10
+#define UA_REFERENCETYPEINDEX_HASTYPEDEFINITION 11
+#define UA_REFERENCETYPEINDEX_GENERATESEVENT 12
+#define UA_REFERENCETYPEINDEX_HASPROPERTY 13
+#define UA_REFERENCETYPEINDEX_HASCOMPONENT 14
+#define UA_REFERENCETYPEINDEX_HASNOTIFIER 15
+#define UA_REFERENCETYPEINDEX_HASORDEREDCOMPONENT 16
+#define UA_REFERENCETYPEINDEX_HASINTERFACE 17
+
+/* The maximum number of ReferrenceTypes. Must be a multiple of 32. */
+#define UA_REFERENCETYPESET_MAX 128
+typedef struct { UA_UInt32 bits[UA_REFERENCETYPESET_MAX / 32]; } UA_ReferenceTypeSet;
+
+static UA_INLINE void
+UA_ReferenceTypeSet_init(UA_ReferenceTypeSet *set) {
+ memset(set, 0, sizeof(UA_ReferenceTypeSet));
+}
+
+static UA_INLINE void
+UA_ReferenceTypeSet_any(UA_ReferenceTypeSet *set) {
+ memset(set, -1, sizeof(UA_ReferenceTypeSet));
+}
+
+static UA_INLINE UA_ReferenceTypeSet
+UA_REFTYPESET(UA_Byte index) {
+ UA_Byte i = index / 32, j = index % 32;
+ UA_ReferenceTypeSet set;
+ UA_ReferenceTypeSet_init(&set);
+ set.bits[i] |= ((UA_UInt32)1) << j;
+ return set;
+}
+
+static UA_INLINE UA_ReferenceTypeSet
+UA_ReferenceTypeSet_union(const UA_ReferenceTypeSet setA,
+ const UA_ReferenceTypeSet setB) {
+ UA_ReferenceTypeSet set;
+ for(size_t i = 0; i < UA_REFERENCETYPESET_MAX / 32; i++)
+ set.bits[i] = setA.bits[i] | setB.bits[i];
+ return set;
+}
+
+static UA_INLINE UA_Boolean
+UA_ReferenceTypeSet_contains(const UA_ReferenceTypeSet *set, UA_Byte index) {
+ UA_Byte i = index / 32, j = index % 32;
+ return !!(set->bits[i] & (((UA_UInt32)1) << j));
+}
+
+/**
+ * Node Pointer
+ * ============
+ *
+ * The "native" format for reference between nodes is the ExpandedNodeId. That
+ * is, references can also point to external servers. In practice, most
+ * references point to local nodes using numerical NodeIds from the
+ * standard-defined namespace zero. In order to save space (and time),
+ * pointer-tagging is used for compressed "NodePointer" representations.
+ * Numerical NodeIds are immediately contained in the pointer. Full NodeIds and
+ * ExpandedNodeIds are behind a pointer indirection. If the Nodestore supports
+ * it, a NodePointer can also be an actual pointer to the target node.
+ *
+ * Depending on the processor architecture, some numerical NodeIds don't fit
+ * into an immediate encoding and are kept as pointers. ExpandedNodeIds may be
+ * internally translated to "normal" NodeIds. Use the provided functions to
+ * generate NodePointers that fit the assumptions for the local architecture. */
+
+/* Forward declaration. All node structures begin with the NodeHead. */
+struct UA_NodeHead;
+typedef struct UA_NodeHead UA_NodeHead;
+
+/* Tagged Pointer structure. */
+typedef union {
+ uintptr_t immediate; /* 00: Small numerical NodeId */
+ const UA_NodeId *id; /* 01: Pointer to NodeId */
+ const UA_ExpandedNodeId *expandedId; /* 10: Pointer to ExternalNodeId */
+ const UA_NodeHead *node; /* 11: Pointer to a node */
+} UA_NodePointer;
+
+/* Sets the pointer to an immediate NodeId "ns=0;i=0" similar to a freshly
+ * initialized UA_NodeId */
+static UA_INLINE void
+UA_NodePointer_init(UA_NodePointer *np) { np->immediate = 0; }
+
+/* NodeId and ExpandedNodeId targets are freed */
+void UA_EXPORT
+UA_NodePointer_clear(UA_NodePointer *np);
+
+/* Makes a deep copy */
+UA_StatusCode UA_EXPORT
+UA_NodePointer_copy(UA_NodePointer in, UA_NodePointer *out);
+
+/* Test if an ExpandedNodeId or a local NodeId */
+UA_Boolean UA_EXPORT
+UA_NodePointer_isLocal(UA_NodePointer np);
+
+UA_Order UA_EXPORT
+UA_NodePointer_order(UA_NodePointer p1, UA_NodePointer p2);
+
+static UA_INLINE UA_Boolean
+UA_NodePointer_equal(UA_NodePointer p1, UA_NodePointer p2) {
+ return (UA_NodePointer_order(p1, p2) == UA_ORDER_EQ);
+}
+
+/* Cannot fail. The resulting NodePointer can point to the memory from the
+ * NodeId. Make a deep copy if required. */
+UA_NodePointer UA_EXPORT
+UA_NodePointer_fromNodeId(const UA_NodeId *id);
+
+/* Cannot fail. The resulting NodePointer can point to the memory from the
+ * ExpandedNodeId. Make a deep copy if required. */
+UA_NodePointer UA_EXPORT
+UA_NodePointer_fromExpandedNodeId(const UA_ExpandedNodeId *id);
+
+/* Can point to the memory from the NodePointer */
+UA_ExpandedNodeId UA_EXPORT
+UA_NodePointer_toExpandedNodeId(UA_NodePointer np);
+
+/* Can point to the memory from the NodePointer. Discards the ServerIndex and
+ * NamespaceUri of a potential ExpandedNodeId inside the NodePointer. Test
+ * before if the NodePointer is local. */
+UA_NodeId UA_EXPORT
+UA_NodePointer_toNodeId(UA_NodePointer np);
+
+/**
* Base Node Attributes
* --------------------
*
@@ -26922,50 +26101,77 @@ struct UA_MonitoredItem;
* not known or not important. The ``nodeClass`` attribute is used to ensure the
* correctness of casting from ``UA_Node`` to a specific node type. */
-/* Ordered tree structure for fast member check */
-typedef struct UA_ReferenceTarget {
- ZIP_ENTRY(UA_ReferenceTarget) idTreeFields;
- ZIP_ENTRY(UA_ReferenceTarget) nameTreeFields;
- UA_UInt32 targetIdHash; /* Hash of the target's NodeId */
- UA_UInt32 targetNameHash; /* Hash of the target's BrowseName */
- UA_ExpandedNodeId targetId;
+typedef struct {
+ UA_NodePointer targetId; /* Has to be the first entry */
+ UA_UInt32 targetNameHash; /* Hash of the target's BrowseName. Set to zero
+ * if the target is remote. */
} UA_ReferenceTarget;
-ZIP_HEAD(UA_ReferenceTargetIdTree, UA_ReferenceTarget);
-typedef struct UA_ReferenceTargetIdTree UA_ReferenceTargetIdTree;
-ZIP_PROTTYPE(UA_ReferenceTargetIdTree, UA_ReferenceTarget, UA_ReferenceTarget)
-
-ZIP_HEAD(UA_ReferenceTargetNameTree, UA_ReferenceTarget);
-typedef struct UA_ReferenceTargetNameTree UA_ReferenceTargetNameTree;
-ZIP_PROTTYPE(UA_ReferenceTargetNameTree, UA_ReferenceTarget, UA_UInt32)
-
-/* List of reference targets with the same reference type and direction */
typedef struct {
- UA_NodeId referenceTypeId;
+ UA_ReferenceTarget target; /* Has to be the first entry */
+ UA_UInt32 targetIdHash; /* Hash of the targetId */
+ struct aa_entry idTreeEntry; /* Binary-Tree for fast lookup */
+ struct aa_entry nameTreeEntry;
+} UA_ReferenceTargetTreeElem;
+
+/* List of reference targets with the same reference type and direction. Uses
+ * either an array or a tree structure. The SDK will not change the type of
+ * reference target structure internally. The nodestore implementations may
+ * switch internally when a node is updated.
+ *
+ * The recommendation is to switch to a tree once the number of refs > 8. */
+typedef struct {
+ union {
+ /* Organize the references in an array. Uses less memory, but incurs
+ * lookups in linear time. Recommended if the number of references is
+ * known to be small. */
+ UA_ReferenceTarget *array;
+
+ /* Organize the references in a tree for fast lookup */
+ struct {
+ struct aa_entry *idTreeRoot; /* Fast lookup based on the target id */
+ struct aa_entry *nameTreeRoot; /* Fast lookup based on the target browseName*/
+ } tree;
+ } targets;
+ size_t targetsSize;
+ UA_Boolean hasRefTree; /* RefTree or RefArray? */
+ UA_Byte referenceTypeIndex;
UA_Boolean isInverse;
- size_t refTargetsSize;
- UA_ReferenceTarget *refTargets;
- UA_ReferenceTargetIdTree refTargetsIdTree;
- UA_ReferenceTargetNameTree refTargetsNameTree;
} UA_NodeReferenceKind;
-#define UA_NODE_BASEATTRIBUTES \
- UA_NodeId nodeId; \
- UA_NodeClass nodeClass; \
- UA_QualifiedName browseName; \
- UA_LocalizedText displayName; \
- UA_LocalizedText description; \
- UA_UInt32 writeMask; \
- size_t referencesSize; \
- UA_NodeReferenceKind *references; \
- \
- /* Members specific to open62541 */ \
- void *context; \
- UA_Boolean constructed; /* Constructors were called */
+/* Iterate over the references. Assumes that "prev" points to a
+ * NodeReferenceKind. If prev == NULL, the first element is returned. At the end
+ * of the iteration, NULL is returned.
+ *
+ * Do not continue the iteration after the rk was modified. */
+UA_EXPORT const UA_ReferenceTarget *
+UA_NodeReferenceKind_iterate(const UA_NodeReferenceKind *rk,
+ const UA_ReferenceTarget *prev);
-typedef struct {
- UA_NODE_BASEATTRIBUTES
-} UA_Node;
+/* Switch between array and tree representation. Does nothing upon error (e.g.
+ * out-of-memory). */
+UA_EXPORT UA_StatusCode
+UA_NodeReferenceKind_switch(UA_NodeReferenceKind *rk);
+
+/* Every Node starts with these attributes */
+struct UA_NodeHead {
+ UA_NodeId nodeId;
+ UA_NodeClass nodeClass;
+ UA_QualifiedName browseName;
+ UA_LocalizedText displayName;
+ UA_LocalizedText description;
+ UA_UInt32 writeMask;
+ size_t referencesSize;
+ UA_NodeReferenceKind *references;
+
+ /* Members specific to open62541 */
+ void *context;
+ UA_Boolean constructed; /* Constructors were called */
+#ifdef UA_ENABLE_SUBSCRIPTIONS
+ UA_MonitoredItem *monitoredItems; /* MonitoredItems for Events and immediate
+ * DataChanges (no sampling interval). */
+#endif
+};
/**
* VariableNode
@@ -26986,7 +26192,7 @@ typedef struct {
* attributes.
*
* Data Type
- * ^^^^^^^^^
+ * ~~~~~~~~~
*
* The (scalar) data type of the variable is constrained to be of a specific
* type or one of its children in the type hierarchy. The data type is given as
@@ -27003,7 +26209,7 @@ typedef struct {
* :ref:`VariableTypeNode` is ensured.
*
* Value Rank
- * ^^^^^^^^^^
+ * ~~~~~~~~~~
*
* This attribute indicates whether the value attribute of the variable is an
* array and how many dimensions the array has. It may have the following
@@ -27019,7 +26225,7 @@ typedef struct {
* :ref:`variabletypenode` is ensured.
*
* Array Dimensions
- * ^^^^^^^^^^^^^^^^
+ * ~~~~~~~~~~~~~~~~
*
* If the value rank permits the value to be a (multi-dimensional) array, the
* exact length in each dimensions can be further constrained with this
@@ -27040,6 +26246,165 @@ typedef enum {
UA_VALUESOURCE_DATASOURCE
} UA_ValueSource;
+typedef struct {
+ /* Called before the value attribute is read. It is possible to write into the
+ * value attribute during onRead (using the write service). The node is
+ * re-opened afterwards so that changes are considered in the following read
+ * operation.
+ *
+ * @param handle Points to user-provided data for the callback.
+ * @param nodeid The identifier of the node.
+ * @param data Points to the current node value.
+ * @param range Points to the numeric range the client wants to read from
+ * (or NULL). */
+ void (*onRead)(UA_Server *server, const UA_NodeId *sessionId,
+ void *sessionContext, const UA_NodeId *nodeid,
+ void *nodeContext, const UA_NumericRange *range,
+ const UA_DataValue *value);
+
+ /* Called after writing the value attribute. The node is re-opened after
+ * writing so that the new value is visible in the callback.
+ *
+ * @param server The server executing the callback
+ * @sessionId The identifier of the session
+ * @sessionContext Additional data attached to the session
+ * in the access control layer
+ * @param nodeid The identifier of the node.
+ * @param nodeUserContext Additional data attached to the node by
+ * the user.
+ * @param nodeConstructorContext Additional data attached to the node
+ * by the type constructor(s).
+ * @param range Points to the numeric range the client wants to write to (or
+ * NULL). */
+ void (*onWrite)(UA_Server *server, const UA_NodeId *sessionId,
+ void *sessionContext, const UA_NodeId *nodeId,
+ void *nodeContext, const UA_NumericRange *range,
+ const UA_DataValue *data);
+} UA_ValueCallback;
+
+typedef struct {
+ /* Copies the data from the source into the provided value.
+ *
+ * !! ZERO-COPY OPERATIONS POSSIBLE !!
+ * It is not required to return a copy of the actual content data. You can
+ * return a pointer to memory owned by the user. Memory can be reused
+ * between read callbacks of a DataSource, as the result is already encoded
+ * on the network buffer between each read operation.
+ *
+ * To use zero-copy reads, set the value of the `value->value` Variant
+ * without copying, e.g. with `UA_Variant_setScalar`. Then, also set
+ * `value->value.storageType` to `UA_VARIANT_DATA_NODELETE` to prevent the
+ * memory being cleaned up. Don't forget to also set `value->hasValue` to
+ * true to indicate the presence of a value.
+ *
+ * @param server The server executing the callback
+ * @param sessionId The identifier of the session
+ * @param sessionContext Additional data attached to the session in the
+ * access control layer
+ * @param nodeId The identifier of the node being read from
+ * @param nodeContext Additional data attached to the node by the user
+ * @param includeSourceTimeStamp If true, then the datasource is expected to
+ * set the source timestamp in the returned value
+ * @param range If not null, then the datasource shall return only a
+ * selection of the (nonscalar) data. Set
+ * UA_STATUSCODE_BADINDEXRANGEINVALID in the value if this does not
+ * apply
+ * @param value The (non-null) DataValue that is returned to the client. The
+ * data source sets the read data, the result status and optionally a
+ * sourcetimestamp.
+ * @return Returns a status code for logging. Error codes intended for the
+ * original caller are set in the value. If an error is returned,
+ * then no releasing of the value is done
+ */
+ UA_StatusCode (*read)(UA_Server *server, const UA_NodeId *sessionId,
+ void *sessionContext, const UA_NodeId *nodeId,
+ void *nodeContext, UA_Boolean includeSourceTimeStamp,
+ const UA_NumericRange *range, UA_DataValue *value);
+
+ /* Write into a data source. This method pointer can be NULL if the
+ * operation is unsupported.
+ *
+ * @param server The server executing the callback
+ * @param sessionId The identifier of the session
+ * @param sessionContext Additional data attached to the session in the
+ * access control layer
+ * @param nodeId The identifier of the node being written to
+ * @param nodeContext Additional data attached to the node by the user
+ * @param range If not NULL, then the datasource shall return only a
+ * selection of the (nonscalar) data. Set
+ * UA_STATUSCODE_BADINDEXRANGEINVALID in the value if this does not
+ * apply
+ * @param value The (non-NULL) DataValue that has been written by the client.
+ * The data source contains the written data, the result status and
+ * optionally a sourcetimestamp
+ * @return Returns a status code for logging. Error codes intended for the
+ * original caller are set in the value. If an error is returned,
+ * then no releasing of the value is done
+ */
+ UA_StatusCode (*write)(UA_Server *server, const UA_NodeId *sessionId,
+ void *sessionContext, const UA_NodeId *nodeId,
+ void *nodeContext, const UA_NumericRange *range,
+ const UA_DataValue *value);
+} UA_DataSource;
+
+/**
+ * .. _value-callback:
+ *
+ * Value Callback
+ * ~~~~~~~~~~~~~~
+ * Value Callbacks can be attached to variable and variable type nodes. If
+ * not ``NULL``, they are called before reading and after writing respectively. */
+typedef struct {
+ /* Called before the value attribute is read. The external value source can be
+ * be updated and/or locked during this notification call. After this function returns
+ * to the core, the external value source is readed immediately.
+ */
+ UA_StatusCode (*notificationRead)(UA_Server *server, const UA_NodeId *sessionId,
+ void *sessionContext, const UA_NodeId *nodeid,
+ void *nodeContext, const UA_NumericRange *range);
+
+ /* Called after writing the value attribute. The node is re-opened after
+ * writing so that the new value is visible in the callback.
+ *
+ * @param server The server executing the callback
+ * @sessionId The identifier of the session
+ * @sessionContext Additional data attached to the session
+ * in the access control layer
+ * @param nodeid The identifier of the node.
+ * @param nodeUserContext Additional data attached to the node by
+ * the user.
+ * @param nodeConstructorContext Additional data attached to the node
+ * by the type constructor(s).
+ * @param range Points to the numeric range the client wants to write to (or
+ * NULL). */
+ UA_StatusCode (*userWrite)(UA_Server *server, const UA_NodeId *sessionId,
+ void *sessionContext, const UA_NodeId *nodeId,
+ void *nodeContext, const UA_NumericRange *range,
+ const UA_DataValue *data);
+} UA_ExternalValueCallback;
+
+typedef enum {
+ UA_VALUEBACKENDTYPE_NONE,
+ UA_VALUEBACKENDTYPE_INTERNAL,
+ UA_VALUEBACKENDTYPE_DATA_SOURCE_CALLBACK,
+ UA_VALUEBACKENDTYPE_EXTERNAL
+} UA_ValueBackendType;
+
+typedef struct {
+ UA_ValueBackendType backendType;
+ union {
+ struct {
+ UA_DataValue value;
+ UA_ValueCallback callback;
+ } internal;
+ UA_DataSource dataSource;
+ struct {
+ UA_DataValue **value;
+ UA_ExternalValueCallback callback;
+ } external;
+ } backend;
+} UA_ValueBackend;
+
#define UA_NODE_VARIABLEATTRIBUTES \
/* Constraints on possible values */ \
UA_NodeId dataType; \
@@ -27047,6 +26412,8 @@ typedef enum {
size_t arrayDimensionsSize; \
UA_UInt32 *arrayDimensions; \
\
+ UA_ValueBackend valueBackend; \
+ \
/* The current value */ \
UA_ValueSource valueSource; \
union { \
@@ -27058,11 +26425,18 @@ typedef enum {
} value;
typedef struct {
- UA_NODE_BASEATTRIBUTES
+ UA_NodeHead head;
UA_NODE_VARIABLEATTRIBUTES
UA_Byte accessLevel;
UA_Double minimumSamplingInterval;
UA_Boolean historizing;
+
+ /* Members specific to open62541 */
+ UA_Boolean isDynamic; /* Some variables are "static" in the sense that they
+ * are not attached to a dynamic process in the
+ * background. Only dynamic variables conserve source
+ * and server timestamp for the value attribute.
+ * Static variables have timestamps of "now". */
} UA_VariableNode;
/**
@@ -27079,7 +26453,7 @@ typedef struct {
* instantiated from ``BaseDataVariable``. */
typedef struct {
- UA_NODE_BASEATTRIBUTES
+ UA_NodeHead head;
UA_NODE_VARIABLEATTRIBUTES
UA_Boolean isAbstract;
@@ -27095,7 +26469,7 @@ typedef struct {
*
* Methods define callable functions and are invoked using the :ref:`Call
* <method-services>` service. MethodNodes may have special properties (variable
- * childen with a ``hasProperty`` reference) with the :ref:`qualifiedname` ``(0,
+ * children with a ``hasProperty`` reference) with the :ref:`qualifiedname` ``(0,
* "InputArguments")`` and ``(0, "OutputArguments")``. The input and output
* arguments are both described via an array of ``UA_Argument``. While the Call
* service uses a generic array of :ref:`variant` for input and output, the
@@ -27105,8 +26479,16 @@ typedef struct {
* object types). For this, the NodeId of the method *and of the object
* providing context* is part of a Call request message. */
+typedef UA_StatusCode
+(*UA_MethodCallback)(UA_Server *server, const UA_NodeId *sessionId,
+ void *sessionContext, const UA_NodeId *methodId,
+ void *methodContext, const UA_NodeId *objectId,
+ void *objectContext, size_t inputSize,
+ const UA_Variant *input, size_t outputSize,
+ UA_Variant *output);
+
typedef struct {
- UA_NODE_BASEATTRIBUTES
+ UA_NodeHead head;
UA_Boolean executable;
/* Members specific to open62541 */
@@ -27126,10 +26508,7 @@ typedef struct {
* objects. */
typedef struct {
- UA_NODE_BASEATTRIBUTES
-#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
- struct UA_MonitoredItem *monitoredItemQueue;
-#endif
+ UA_NodeHead head;
UA_Byte eventNotifier;
} UA_ObjectNode;
@@ -27144,7 +26523,7 @@ typedef struct {
* destructor callbacks. */
typedef struct {
- UA_NODE_BASEATTRIBUTES
+ UA_NodeHead head;
UA_Boolean isAbstract;
/* Members specific to open62541 */
@@ -27255,10 +26634,14 @@ typedef struct {
* based on a common understanding of just two custom reference types. */
typedef struct {
- UA_NODE_BASEATTRIBUTES
+ UA_NodeHead head;
UA_Boolean isAbstract;
UA_Boolean symmetric;
UA_LocalizedText inverseName;
+
+ /* Members specific to open62541 */
+ UA_Byte referenceTypeIndex;
+ UA_ReferenceTypeSet subTypes; /* contains the type itself as well */
} UA_ReferenceTypeNode;
/**
@@ -27277,7 +26660,7 @@ typedef struct {
* ``UInt32``). */
typedef struct {
- UA_NODE_BASEATTRIBUTES
+ UA_NodeHead head;
UA_Boolean isAbstract;
} UA_DataTypeNode;
@@ -27292,12 +26675,32 @@ typedef struct {
* open62541. */
typedef struct {
- UA_NODE_BASEATTRIBUTES
+ UA_NodeHead head;
UA_Byte eventNotifier;
UA_Boolean containsNoLoops;
} UA_ViewNode;
/**
+ * Node Union
+ * ----------
+ *
+ * A union that represents any kind of node. The node head can always be used.
+ * Check the NodeClass before accessing specific content.
+ */
+
+typedef union {
+ UA_NodeHead head;
+ UA_VariableNode variableNode;
+ UA_VariableTypeNode variableTypeNode;
+ UA_MethodNode methodNode;
+ UA_ObjectNode objectNode;
+ UA_ObjectTypeNode objectTypeNode;
+ UA_ReferenceTypeNode referenceTypeNode;
+ UA_DataTypeNode dataTypeNode;
+ UA_ViewNode viewNode;
+} UA_Node;
+
+/**
* Nodestore Plugin API
* --------------------
*
@@ -27351,6 +26754,11 @@ typedef struct {
/* Removes a node from the nodestore. */
UA_StatusCode (*removeNode)(void *nsCtx, const UA_NodeId *nodeId);
+ /* Maps the ReferenceTypeIndex used for the references to the NodeId of the
+ * ReferenceType. The returned pointer is stable until the Nodestore is
+ * deleted. */
+ const UA_NodeId * (*getReferenceTypeId)(void *nsCtx, UA_Byte refTypeIndex);
+
/* Execute a callback for every node in the nodestore. */
void (*iterate)(void *nsCtx, UA_NodestoreVisitor visitor,
void *visitorCtx);
@@ -27375,12 +26783,20 @@ UA_Node_copy_alloc(const UA_Node *src);
/* Add a single reference to the node */
UA_StatusCode UA_EXPORT
-UA_Node_addReference(UA_Node *node, const UA_AddReferencesItem *item,
+UA_Node_addReference(UA_Node *node, UA_Byte refTypeIndex, UA_Boolean isForward,
+ const UA_ExpandedNodeId *targetNodeId,
UA_UInt32 targetBrowseNameHash);
/* Delete a single reference from the node */
UA_StatusCode UA_EXPORT
-UA_Node_deleteReference(UA_Node *node, const UA_DeleteReferencesItem *item);
+UA_Node_deleteReference(UA_Node *node, UA_Byte refTypeIndex, UA_Boolean isForward,
+ const UA_ExpandedNodeId *targetNodeId);
+
+/* Deletes references from the node which are not matching any type in the given
+ * array. Could be used to e.g. delete all the references, except
+ * 'HASMODELINGRULE' */
+void UA_EXPORT
+UA_Node_deleteReferencesSubset(UA_Node *node, const UA_ReferenceTypeSet *keepSet);
/* Delete all references of the node */
void UA_EXPORT
@@ -27393,7 +26809,7 @@ UA_Node_clear(UA_Node *node);
_UA_END_DECLS
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/include/open62541/plugin/historydatabase.h" ***********************************/
+/**** amalgamated original file "/include/open62541/plugin/historydatabase.h" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -27439,28 +26855,18 @@ struct UA_HistoryDatabase {
*
* server is the server this node lives in.
* hdbContext is the context of the UA_HistoryDatabase.
- * sessionId and sessionContext identify the session which set this value.
* originId is the node id of the event's origin.
* emitterId is the node id of the event emitter.
- * eventId is the node id of the event that is being emitted.
- * willEventNodeBeDeleted specifies whether the event node will be deleted after
- * it has been triggered (this might be relevant for
- * in-memory storage).
* historicalEventFilter is the value of the HistoricalEventFilter property of
* the emitter (OPC UA Part 11, 5.3.2), it is NULL if
* the property does not exist or is not set.
* fieldList is the event field list returned after application of
- * historicalEventFilter to the event node
- * (NULL if historicalEventFilter is NULL or filtering was
- * unsuccessful); the fieldList is not deleted so
- * make sure to delete it when it is no longer needed. */
+ * historicalEventFilter to the event node. */
void
(*setEvent)(UA_Server *server,
void *hdbContext,
const UA_NodeId *originId,
const UA_NodeId *emitterId,
- const UA_NodeId *eventId,
- UA_Boolean willEventNodeBeDeleted,
const UA_EventFilter *historicalEventFilter,
UA_EventFieldList *fieldList);
@@ -27589,21 +26995,856 @@ struct UA_HistoryDatabase {
_UA_END_DECLS
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/include/open62541/server_config.h" ***********************************/
+/**** amalgamated original file "/include/open62541/server_pubsub.h" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
- * Copyright 2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
- * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
+ * Copyright (c) 2017-2018 Fraunhofer IOSB (Author: Andreas Ebner)
+ * Copyright (c) 2019 Kalycito Infotech Private Limited
+ * Copyright (c) 2021 Fraunhofer IOSB (Author: Jan Hermes)
+ */
+
+#ifndef UA_SERVER_PUBSUB_H
+#define UA_SERVER_PUBSUB_H
+
+
+_UA_BEGIN_DECLS
+
+#ifdef UA_ENABLE_PUBSUB
+
+/**
+ * .. _pubsub:
+ *
+ * PubSub
+ * ======
+ *
+ * In PubSub the participating OPC UA Applications take their roles as
+ * Publishers and Subscribers. Publishers are the sources of data, while
+ * Subscribers consume that data. Communication in PubSub is message-based.
+ * Publishers send messages to a Message Oriented Middleware, without knowledge
+ * of what, if any, Subscribers there may be. Similarly, Subscribers express
+ * interest in specific types of data, and process messages that contain this
+ * data, without knowledge of what Publishers there are.
+ *
+ * Message Oriented Middleware is software or hardware infrastructure that
+ * supports sending and receiving messages between distributed systems. OPC UA
+ * PubSub supports two different Message Oriented Middleware variants, namely
+ * the broker-less form and broker-based form. A broker-less form is where the
+ * Message Oriented Middleware is the network infrastructure that is able to
+ * route datagram-based messages. Subscribers and Publishers use datagram
+ * protocols like UDP. In a broker-based form, the core component of the Message
+ * Oriented Middleware is a message Broker. Subscribers and Publishers use
+ * standard messaging protocols like AMQP or MQTT to communicate with the
+ * Broker.
+ *
+ * This makes PubSub suitable for applications where location independence
+ * and/or scalability are required.
+ *
+ * The Publish/Subscribe (PubSub) extension for OPC UA enables fast and
+ * efficient 1:m communication. The PubSub extension is protocol agnostic and
+ * can be used with broker based protocols like MQTT and AMQP or brokerless
+ * implementations like UDP-Multicasting.
+ *
+ * The PubSub API uses the following scheme:
+ *
+ * 1. Create a configuration for the needed PubSub element.
+ *
+ * 2. Call the add[element] function and pass in the configuration.
+ *
+ * 3. The add[element] function returns the unique nodeId of the internally created element.
+ *
+ * Take a look on the PubSub Tutorials for more details about the API usage::
+ *
+ * +-----------+
+ * | UA_Server |
+ * +-----------+
+ * | |
+ * | |
+ * | |
+ * | | +----------------------+
+ * | +--> UA_PubSubConnection | UA_Server_addPubSubConnection
+ * | +----------------------+
+ * | | |
+ * | | | +----------------+
+ * | | +----> UA_WriterGroup | UA_PubSubConnection_addWriterGroup
+ * | | +----------------+
+ * | | |
+ * | | | +------------------+
+ * | | +----> UA_DataSetWriter | UA_WriterGroup_addDataSetWriter +-+
+ * | | +------------------+ |
+ * | | |
+ * | | +----------------+ | r
+ * | +---------> UA_ReaderGroup | UA_PubSubConnection_addReaderGroup | e
+ * | +----------------+ | f
+ * | | |
+ * | | +------------------+ |
+ * | +----> UA_DataSetReader | UA_ReaderGroup_addDataSetReader |
+ * | +------------------+ |
+ * | | |
+ * | | +----------------------+ |
+ * | +----> UA_SubscribedDataSet | |
+ * | +----------------------+ |
+ * | | |
+ * | | +----------------------------+ |
+ * | +----> UA_TargetVariablesDataType | |
+ * | | +----------------------------+ |
+ * | | |
+ * | | +------------------------------------+ |
+ * | +----> UA_SubscribedDataSetMirrorDataType | |
+ * | +------------------------------------+ |
+ * | |
+ * | +---------------------------+ |
+ * +-------> UA_PubSubPublishedDataSet | UA_Server_addPublishedDataSet <-+
+ * +---------------------------+
+ * |
+ * | +-----------------+
+ * +----> UA_DataSetField | UA_PublishedDataSet_addDataSetField
+ * +-----------------+
+ *
+ * PubSub Information Model Representation
+ * ---------------------------------------
+ * .. _pubsub_informationmodel:
+ *
+ * The complete PubSub configuration is available inside the information model.
+ * The entry point is the node 'PublishSubscribe', located under the Server
+ * node.
+ * The standard defines for PubSub no new Service set. The configuration can
+ * optionally be done over methods inside the information model.
+ * The information model representation of the current PubSub configuration is
+ * generated automatically. This feature can be enabled/disabled by changing the
+ * UA_ENABLE_PUBSUB_INFORMATIONMODEL option.
+ *
+ * Connections
+ * -----------
+ * The PubSub connections are the abstraction between the concrete transport protocol
+ * and the PubSub functionality. It is possible to create multiple connections with
+ * different transport protocols at runtime.
+ *
+ * Take a look on the PubSub Tutorials for mor details about the API usage.
+ */
+
+typedef enum {
+ UA_PUBSUB_COMPONENT_CONNECTION,
+ UA_PUBSUB_COMPONENT_WRITERGROUP,
+ UA_PUBSUB_COMPONENT_DATASETWRITER,
+ UA_PUBSUB_COMPONENT_READERGROUP,
+ UA_PUBSUB_COMPONENT_DATASETREADER
+} UA_PubSubComponentEnumType;
+
+typedef enum {
+ UA_PUBSUB_PUBLISHERID_NUMERIC,
+ UA_PUBSUB_PUBLISHERID_STRING
+} UA_PublisherIdType;
+
+struct UA_PubSubConnectionConfig {
+ UA_String name;
+ UA_Boolean enabled;
+ UA_PublisherIdType publisherIdType;
+ union { /* std: valid types UInt or String */
+ UA_UInt32 numeric;
+ UA_String string;
+ } publisherId;
+ UA_String transportProfileUri;
+ UA_Variant address;
+ size_t connectionPropertiesSize;
+ UA_KeyValuePair *connectionProperties;
+ UA_Variant connectionTransportSettings;
+};
+
+#ifdef UA_ENABLE_PUBSUB_MONITORING
+
+typedef enum {
+ UA_PUBSUB_MONITORING_MESSAGE_RECEIVE_TIMEOUT
+ // extend as needed
+} UA_PubSubMonitoringType;
+
+/* PubSub monitoring interface */
+typedef struct {
+ UA_StatusCode (*createMonitoring)(UA_Server *server, UA_NodeId Id,
+ UA_PubSubComponentEnumType eComponentType,
+ UA_PubSubMonitoringType eMonitoringType,
+ void *data, UA_ServerCallback callback);
+ UA_StatusCode (*startMonitoring)(UA_Server *server, UA_NodeId Id,
+ UA_PubSubComponentEnumType eComponentType,
+ UA_PubSubMonitoringType eMonitoringType, void *data);
+ UA_StatusCode (*stopMonitoring)(UA_Server *server, UA_NodeId Id,
+ UA_PubSubComponentEnumType eComponentType,
+ UA_PubSubMonitoringType eMonitoringType, void *data);
+ UA_StatusCode (*updateMonitoringInterval)(UA_Server *server, UA_NodeId Id,
+ UA_PubSubComponentEnumType eComponentType,
+ UA_PubSubMonitoringType eMonitoringType,
+ void *data);
+ UA_StatusCode (*deleteMonitoring)(UA_Server *server, UA_NodeId Id,
+ UA_PubSubComponentEnumType eComponentType,
+ UA_PubSubMonitoringType eMonitoringType, void *data);
+} UA_PubSubMonitoringInterface;
+
+#endif /* UA_ENABLE_PUBSUB_MONITORING */
+
+/* General PubSub configuration */
+struct UA_PubSubConfiguration {
+ /* PubSub network layer */
+ size_t transportLayersSize;
+ UA_PubSubTransportLayer *transportLayers;
+
+ /* Callback for PubSub component state changes: If provided this callback
+ * informs the application about PubSub component state changes. E.g. state
+ * change from operational to error in case of a DataSetReader
+ * MessageReceiveTimeout. The status code provides additional
+ * information. */
+ void (*stateChangeCallback)(UA_NodeId *Id, UA_PubSubState state,
+ UA_StatusCode status);
+ /* TODO: maybe status code provides not enough information about the state change */
+
+#ifdef UA_ENABLE_PUBSUB_ENCRYPTION
+ /* PubSub security policies */
+ size_t securityPoliciesSize;
+ UA_PubSubSecurityPolicy *securityPolicies;
+#endif
+
+#ifdef UA_ENABLE_PUBSUB_MONITORING
+ UA_PubSubMonitoringInterface monitoringInterface;
+#endif
+};
+
+
+/**
+ * The UA_ServerConfig_addPubSubTransportLayer is used to add a transport layer
+ * to the server configuration. The list memory is allocated and will be freed
+ * with UA_PubSubManager_delete.
+ *
+ * .. note:: If the UA_String transportProfileUri was dynamically allocated
+ * the memory has to be freed when no longer required.
+ *
+ * .. note:: This has to be done before the server is started with UA_Server_run. */
+
+UA_StatusCode UA_EXPORT
+UA_ServerConfig_addPubSubTransportLayer(UA_ServerConfig *config,
+ UA_PubSubTransportLayer pubsubTransportLayer);
+
+UA_StatusCode UA_EXPORT
+UA_Server_addPubSubConnection(UA_Server *server,
+ const UA_PubSubConnectionConfig *connectionConfig,
+ UA_NodeId *connectionIdentifier);
+
+/* Returns a deep copy of the config */
+UA_StatusCode UA_EXPORT
+UA_Server_getPubSubConnectionConfig(UA_Server *server,
+ const UA_NodeId connection,
+ UA_PubSubConnectionConfig *config);
+
+/* Remove Connection, identified by the NodeId. Deletion of Connection
+ * removes all contained WriterGroups and Writers. */
+UA_StatusCode UA_EXPORT
+UA_Server_removePubSubConnection(UA_Server *server, const UA_NodeId connection);
+
+/**
+ * PublishedDataSets
+ * -----------------
+ * The PublishedDataSets (PDS) are containers for the published information. The
+ * PDS contain the published variables and meta information. The metadata is
+ * commonly autogenerated or given as constant argument as part of the template
+ * functions. The template functions are standard defined and intended for
+ * configuration tools. You should normally create an empty PDS and call the
+ * functions to add new fields. */
+
+/* The UA_PUBSUB_DATASET_PUBLISHEDITEMS has currently no additional members and
+ * thus no dedicated config structure. */
+
+typedef enum {
+ UA_PUBSUB_DATASET_PUBLISHEDITEMS,
+ UA_PUBSUB_DATASET_PUBLISHEDEVENTS,
+ UA_PUBSUB_DATASET_PUBLISHEDITEMS_TEMPLATE,
+ UA_PUBSUB_DATASET_PUBLISHEDEVENTS_TEMPLATE,
+} UA_PublishedDataSetType;
+
+typedef struct {
+ UA_DataSetMetaDataType metaData;
+ size_t variablesToAddSize;
+ UA_PublishedVariableDataType *variablesToAdd;
+} UA_PublishedDataItemsTemplateConfig;
+
+typedef struct {
+ UA_NodeId eventNotfier;
+ UA_ContentFilter filter;
+} UA_PublishedEventConfig;
+
+typedef struct {
+ UA_DataSetMetaDataType metaData;
+ UA_NodeId eventNotfier;
+ size_t selectedFieldsSize;
+ UA_SimpleAttributeOperand *selectedFields;
+ UA_ContentFilter filter;
+} UA_PublishedEventTemplateConfig;
+
+/* Configuration structure for PublishedDataSet */
+typedef struct {
+ UA_String name;
+ UA_PublishedDataSetType publishedDataSetType;
+ union {
+ /* The UA_PUBSUB_DATASET_PUBLISHEDITEMS has currently no additional members
+ * and thus no dedicated config structure.*/
+ UA_PublishedDataItemsTemplateConfig itemsTemplate;
+ UA_PublishedEventConfig event;
+ UA_PublishedEventTemplateConfig eventTemplate;
+ } config;
+} UA_PublishedDataSetConfig;
+
+void UA_EXPORT
+UA_PublishedDataSetConfig_clear(UA_PublishedDataSetConfig *pdsConfig);
+
+typedef struct {
+ UA_StatusCode addResult;
+ size_t fieldAddResultsSize;
+ UA_StatusCode *fieldAddResults;
+ UA_ConfigurationVersionDataType configurationVersion;
+} UA_AddPublishedDataSetResult;
+
+UA_AddPublishedDataSetResult UA_EXPORT
+UA_Server_addPublishedDataSet(UA_Server *server,
+ const UA_PublishedDataSetConfig *publishedDataSetConfig,
+ UA_NodeId *pdsIdentifier);
+
+/* Returns a deep copy of the config */
+UA_StatusCode UA_EXPORT
+UA_Server_getPublishedDataSetConfig(UA_Server *server, const UA_NodeId pds,
+ UA_PublishedDataSetConfig *config);
+
+/* Returns a deep copy of the DataSetMetaData for an specific PDS */
+UA_StatusCode UA_EXPORT
+UA_Server_getPublishedDataSetMetaData(UA_Server *server, const UA_NodeId pds,
+ UA_DataSetMetaDataType *metaData);
+
+/* Remove PublishedDataSet, identified by the NodeId. Deletion of PDS removes
+ * all contained and linked PDS Fields. Connected WriterGroups will be also
+ * removed. */
+UA_StatusCode UA_EXPORT
+UA_Server_removePublishedDataSet(UA_Server *server, const UA_NodeId pds);
+
+/**
+ * DataSetFields
+ * -------------
+ * The description of published variables is named DataSetField. Each
+ * DataSetField contains the selection of one information model node. The
+ * DataSetField has additional parameters for the publishing, sampling and error
+ * handling process. */
+
+typedef struct{
+ UA_ConfigurationVersionDataType configurationVersion;
+ UA_String fieldNameAlias;
+ UA_Boolean promotedField;
+ UA_PublishedVariableDataType publishParameters;
+
+ /* non std. field */
+ struct {
+ UA_Boolean rtFieldSourceEnabled;
+ /* If the rtInformationModelNode is set, the nodeid in publishParameter must point
+ * to a node with external data source backend defined
+ * */
+ UA_Boolean rtInformationModelNode;
+ //TODO -> decide if suppress C++ warnings and use 'UA_DataValue * * const staticValueSource;'
+ UA_DataValue ** staticValueSource;
+ } rtValueSource;
+
+
+} UA_DataSetVariableConfig;
+
+typedef enum {
+ UA_PUBSUB_DATASETFIELD_VARIABLE,
+ UA_PUBSUB_DATASETFIELD_EVENT
+} UA_DataSetFieldType;
+
+typedef struct {
+ UA_DataSetFieldType dataSetFieldType;
+ union {
+ /* events need other config later */
+ UA_DataSetVariableConfig variable;
+ } field;
+} UA_DataSetFieldConfig;
+
+void UA_EXPORT
+UA_DataSetFieldConfig_clear(UA_DataSetFieldConfig *dataSetFieldConfig);
+
+typedef struct {
+ UA_StatusCode result;
+ UA_ConfigurationVersionDataType configurationVersion;
+} UA_DataSetFieldResult;
+
+UA_DataSetFieldResult UA_EXPORT
+UA_Server_addDataSetField(UA_Server *server,
+ const UA_NodeId publishedDataSet,
+ const UA_DataSetFieldConfig *fieldConfig,
+ UA_NodeId *fieldIdentifier);
+
+/* Returns a deep copy of the config */
+UA_StatusCode UA_EXPORT
+UA_Server_getDataSetFieldConfig(UA_Server *server, const UA_NodeId dsf,
+ UA_DataSetFieldConfig *config);
+
+UA_DataSetFieldResult UA_EXPORT
+UA_Server_removeDataSetField(UA_Server *server, const UA_NodeId dsf);
+
+/**
+ * Custom Callback Implementation
+ * ------------------------------
+ * The user can use his own callback implementation for publishing
+ * and subscribing. The user must take care of the callback to call for
+ * every publishing or subscibing interval */
+
+typedef struct {
+ /* User's callback implementation. The user configured base time and timer policy
+ * will be provided as an argument to this callback so that the user can
+ * implement his callback (thread) considering base time and timer policies */
+ UA_StatusCode (*addCustomCallback)(UA_Server *server, UA_NodeId identifier,
+ UA_ServerCallback callback,
+ void *data, UA_Double interval_ms,
+ UA_DateTime *baseTime, UA_TimerPolicy timerPolicy,
+ UA_UInt64 *callbackId);
+
+ UA_StatusCode (*changeCustomCallback)(UA_Server *server, UA_NodeId identifier,
+ UA_UInt64 callbackId, UA_Double interval_ms,
+ UA_DateTime *baseTime, UA_TimerPolicy timerPolicy);
+
+ void (*removeCustomCallback)(UA_Server *server, UA_NodeId identifier, UA_UInt64 callbackId);
+
+} UA_PubSub_CallbackLifecycle;
+
+/**
+ * WriterGroup
+ * -----------
+ * All WriterGroups are created within a PubSubConnection and automatically
+ * deleted if the connection is removed. The WriterGroup is primary used as
+ * container for :ref:`dsw` and network message settings. The WriterGroup can be
+ * imagined as producer of the network messages. The creation of network
+ * messages is controlled by parameters like the publish interval, which is e.g.
+ * contained in the WriterGroup. */
+
+typedef enum {
+ UA_PUBSUB_ENCODING_BINARY,
+ UA_PUBSUB_ENCODING_JSON,
+ UA_PUBSUB_ENCODING_UADP
+} UA_PubSubEncodingType;
+
+/**
+ * WriterGroup
+ * -----------
+ * The message publishing can be configured for realtime requirements. The RT-levels
+ * go along with different requirements. The below listed levels can be configured:
+ *
+ * UA_PUBSUB_RT_NONE -
+ * ---> Description: Default "none-RT" Mode
+ * ---> Requirements: -
+ * ---> Restrictions: -
+ * UA_PUBSUB_RT_DIRECT_VALUE_ACCESS (Preview - not implemented)
+ * ---> Description: Normally, the latest value for each DataSetField is read out of the information model. Within this RT-mode, the
+ * value source of each field configured as static pointer to an DataValue. The publish cycle won't use call the server read function.
+ * ---> Requirements: All fields must be configured with a 'staticValueSource'.
+ * ---> Restrictions: -
+ * UA_PUBSUB_RT_FIXED_LENGTH (Preview - not implemented)
+ * ---> Description: All DataSetFields have a known, non-changing length. The server will pre-generate some
+ * buffers and use only memcopy operations to generate requested PubSub packages.
+ * ---> Requirements: DataSetFields with variable size cannot be used within this mode.
+ * ---> Restrictions: The configuration must be frozen and changes are not allowed while the WriterGroup is 'Operational'.
+ * UA_PUBSUB_RT_DETERMINISTIC (Preview - not implemented)
+ * ---> Description: -
+ * ---> Requirements: -
+ * ---> Restrictions: -
+ *
+ * WARNING! For hard real time requirements the underlying system must be rt-capable.
+ *
+ */
+typedef enum {
+ UA_PUBSUB_RT_NONE = 0,
+ UA_PUBSUB_RT_DIRECT_VALUE_ACCESS = 1,
+ UA_PUBSUB_RT_FIXED_SIZE = 2,
+ UA_PUBSUB_RT_DETERMINISTIC = 4,
+} UA_PubSubRTLevel;
+
+typedef struct {
+ UA_String name;
+ UA_Boolean enabled;
+ UA_UInt16 writerGroupId;
+ UA_Duration publishingInterval;
+ UA_Double keepAliveTime;
+ UA_Byte priority;
+ UA_ExtensionObject transportSettings;
+ UA_ExtensionObject messageSettings;
+ size_t groupPropertiesSize;
+ UA_KeyValuePair *groupProperties;
+ UA_PubSubEncodingType encodingMimeType;
+ /* PubSub Manager Callback */
+ UA_PubSub_CallbackLifecycle pubsubManagerCallback;
+ /* non std. config parameter. maximum count of embedded DataSetMessage in
+ * one NetworkMessage */
+ UA_UInt16 maxEncapsulatedDataSetMessageCount;
+ /* non std. field */
+ UA_PubSubRTLevel rtLevel;
+
+ /* Message are encrypted if a SecurityPolicy is configured and the
+ * securityMode set accordingly. The symmetric key is a runtime information
+ * and has to be set via UA_Server_setWriterGroupEncryptionKey. */
+ UA_MessageSecurityMode securityMode; /* via the UA_WriterGroupDataType */
+#ifdef UA_ENABLE_PUBSUB_ENCRYPTION
+ UA_PubSubSecurityPolicy *securityPolicy;
+#endif
+} UA_WriterGroupConfig;
+
+void UA_EXPORT
+UA_WriterGroupConfig_clear(UA_WriterGroupConfig *writerGroupConfig);
+
+/* Add a new WriterGroup to an existing Connection */
+UA_StatusCode UA_EXPORT
+UA_Server_addWriterGroup(UA_Server *server, const UA_NodeId connection,
+ const UA_WriterGroupConfig *writerGroupConfig,
+ UA_NodeId *writerGroupIdentifier);
+
+/* Returns a deep copy of the config */
+UA_StatusCode UA_EXPORT
+UA_Server_getWriterGroupConfig(UA_Server *server, const UA_NodeId writerGroup,
+ UA_WriterGroupConfig *config);
+
+UA_StatusCode UA_EXPORT
+UA_Server_updateWriterGroupConfig(UA_Server *server, UA_NodeId writerGroupIdentifier,
+ const UA_WriterGroupConfig *config);
+
+/* Get state of WriterGroup */
+UA_StatusCode UA_EXPORT
+UA_Server_WriterGroup_getState(UA_Server *server, UA_NodeId writerGroupIdentifier,
+ UA_PubSubState *state);
+
+UA_StatusCode UA_EXPORT
+UA_Server_removeWriterGroup(UA_Server *server, const UA_NodeId writerGroup);
+
+UA_StatusCode UA_EXPORT
+UA_Server_freezeWriterGroupConfiguration(UA_Server *server, const UA_NodeId writerGroup);
+
+UA_StatusCode UA_EXPORT
+UA_Server_unfreezeWriterGroupConfiguration(UA_Server *server, const UA_NodeId writerGroup);
+
+UA_StatusCode UA_EXPORT
+UA_Server_setWriterGroupOperational(UA_Server *server, const UA_NodeId writerGroup);
+
+UA_StatusCode UA_EXPORT
+UA_Server_setWriterGroupDisabled(UA_Server *server, const UA_NodeId writerGroup);
+
+#ifdef UA_ENABLE_PUBSUB_ENCRYPTION
+/* Set the group key for the message encryption */
+UA_StatusCode UA_EXPORT
+UA_Server_setWriterGroupEncryptionKeys(UA_Server *server, const UA_NodeId writerGroup,
+ UA_UInt32 securityTokenId,
+ const UA_ByteString signingKey,
+ const UA_ByteString encryptingKey,
+ const UA_ByteString keyNonce);
+#endif
+
+/**
+ * .. _dsw:
+ *
+ * DataSetWriter
+ * -------------
+ * The DataSetWriters are the glue between the WriterGroups and the
+ * PublishedDataSets. The DataSetWriter contain configuration parameters and
+ * flags which influence the creation of DataSet messages. These messages are
+ * encapsulated inside the network message. The DataSetWriter must be linked
+ * with an existing PublishedDataSet and be contained within a WriterGroup. */
+
+typedef struct {
+ UA_String name;
+ UA_UInt16 dataSetWriterId;
+ UA_DataSetFieldContentMask dataSetFieldContentMask;
+ UA_UInt32 keyFrameCount;
+ UA_ExtensionObject messageSettings;
+ UA_ExtensionObject transportSettings;
+ UA_String dataSetName;
+ size_t dataSetWriterPropertiesSize;
+ UA_KeyValuePair *dataSetWriterProperties;
+} UA_DataSetWriterConfig;
+
+void UA_EXPORT
+UA_DataSetWriterConfig_clear(UA_DataSetWriterConfig *pdsConfig);
+
+/* Add a new DataSetWriter to an existing WriterGroup. The DataSetWriter must be
+ * coupled with a PublishedDataSet on creation.
+ *
+ * Part 14, 7.1.5.2.1 defines: The link between the PublishedDataSet and
+ * DataSetWriter shall be created when an instance of the DataSetWriterType is
+ * created. */
+UA_StatusCode UA_EXPORT
+UA_Server_addDataSetWriter(UA_Server *server,
+ const UA_NodeId writerGroup, const UA_NodeId dataSet,
+ const UA_DataSetWriterConfig *dataSetWriterConfig,
+ UA_NodeId *writerIdentifier);
+
+/* Returns a deep copy of the config */
+UA_StatusCode UA_EXPORT
+UA_Server_getDataSetWriterConfig(UA_Server *server, const UA_NodeId dsw,
+ UA_DataSetWriterConfig *config);
+
+/* Get state of DataSetWriter */
+UA_StatusCode UA_EXPORT
+UA_Server_DataSetWriter_getState(UA_Server *server, UA_NodeId dataSetWriterIdentifier,
+ UA_PubSubState *state);
+
+UA_StatusCode UA_EXPORT
+UA_Server_removeDataSetWriter(UA_Server *server, const UA_NodeId dsw);
+
+/**
+ * SubscribedDataSet
+ * -----------------
+ * SubscribedDataSet describes the processing of the received DataSet.
+ * SubscribedDataSet defines which field in the DataSet is mapped to which
+ * Variable in the OPC UA Application. SubscribedDataSet has two sub-types
+ * called the TargetVariablesType and SubscribedDataSetMirrorType.
+ * SubscribedDataSetMirrorType is currently not supported. SubscribedDataSet is
+ * set to TargetVariablesType and then the list of target Variables are created
+ * in the Subscriber AddressSpace. TargetVariables are a list of variables that
+ * are to be added in the Subscriber AddressSpace. It defines a list of Variable
+ * mappings between received DataSet fields and added Variables in the
+ * Subscriber AddressSpace. */
+
+/* SubscribedDataSetDataType Definition */
+typedef enum {
+ UA_PUBSUB_SDS_TARGET,
+ UA_PUBSUB_SDS_MIRROR
+} UA_SubscribedDataSetEnumType;
+
+typedef struct {
+ /* Standard-defined FieldTargetDataType */
+ UA_FieldTargetDataType targetVariable;
+
+ /* If realtime-handling is required, set this pointer non-NULL and it will be used
+ * to memcpy the value instead of using the Write service.
+ * If the beforeWrite method pointer is set, it will be called before a memcpy update
+ * to the value. But param externalDataValue already contains the new value.
+ * If the afterWrite method pointer is set, it will be called after a memcpy update
+ * to the value. */
+ UA_DataValue **externalDataValue;
+ void *targetVariableContext; /* user-defined pointer */
+ void (*beforeWrite)(UA_Server *server,
+ const UA_NodeId *readerIdentifier,
+ const UA_NodeId *readerGroupIdentifier,
+ const UA_NodeId *targetVariableIdentifier,
+ void *targetVariableContext,
+ UA_DataValue **externalDataValue);
+ void (*afterWrite)(UA_Server *server,
+ const UA_NodeId *readerIdentifier,
+ const UA_NodeId *readerGroupIdentifier,
+ const UA_NodeId *targetVariableIdentifier,
+ void *targetVariableContext,
+ UA_DataValue **externalDataValue);
+} UA_FieldTargetVariable;
+
+typedef struct {
+ size_t targetVariablesSize;
+ UA_FieldTargetVariable *targetVariables;
+} UA_TargetVariables;
+
+/* Return Status Code after creating TargetVariables in Subscriber AddressSpace */
+UA_StatusCode UA_EXPORT
+UA_Server_DataSetReader_createTargetVariables(UA_Server *server,
+ UA_NodeId dataSetReaderIdentifier,
+ size_t targetVariablesSize,
+ const UA_FieldTargetVariable *targetVariables);
+
+/* To Do:Implementation of SubscribedDataSetMirrorType
+ * UA_StatusCode
+ * A_PubSubDataSetReader_createDataSetMirror(UA_Server *server, UA_NodeId dataSetReaderIdentifier,
+ * UA_SubscribedDataSetMirrorDataType* mirror) */
+
+/**
+ * DataSetReader
+ * -------------
+ * DataSetReader can receive NetworkMessages with the DataSetMessage
+ * of interest sent by the Publisher. DataSetReaders represent
+ * the configuration necessary to receive and process DataSetMessages
+ * on the Subscriber side. DataSetReader must be linked with a
+ * SubscribedDataSet and be contained within a ReaderGroup. */
+
+/* Parameters for PubSubSecurity */
+typedef struct {
+ UA_Int32 securityMode; /* placeholder datatype 'MessageSecurityMode' */
+ UA_String securityGroupId;
+ size_t keyServersSize;
+ UA_Int32 *keyServers;
+} UA_PubSubSecurityParameters;
+
+typedef enum {
+ UA_PUBSUB_RT_UNKNOWN = 0,
+ UA_PUBSUB_RT_VARIANT = 1,
+ UA_PUBSUB_RT_DATA_VALUE = 2,
+ UA_PUBSUB_RT_RAW = 4,
+} UA_PubSubRtEncoding;
+
+/* Parameters for PubSub DataSetReader Configuration */
+typedef struct {
+ UA_String name;
+ UA_Variant publisherId;
+ UA_UInt16 writerGroupId;
+ UA_UInt16 dataSetWriterId;
+ UA_DataSetMetaDataType dataSetMetaData;
+ UA_DataSetFieldContentMask dataSetFieldContentMask;
+ UA_Double messageReceiveTimeout;
+ UA_PubSubSecurityParameters securityParameters;
+ UA_ExtensionObject messageSettings;
+ UA_ExtensionObject transportSettings;
+ UA_SubscribedDataSetEnumType subscribedDataSetType;
+ /* TODO UA_SubscribedDataSetMirrorDataType subscribedDataSetMirror */
+ union {
+ UA_TargetVariables subscribedDataSetTarget;
+ // UA_SubscribedDataSetMirrorDataType subscribedDataSetMirror;
+ } subscribedDataSet;
+ /* non std. fields */
+ UA_PubSubRtEncoding expectedEncoding;
+} UA_DataSetReaderConfig;
+
+/* Update configuration to the dataSetReader */
+UA_StatusCode UA_EXPORT
+UA_Server_DataSetReader_updateConfig(UA_Server *server, UA_NodeId dataSetReaderIdentifier,
+ UA_NodeId readerGroupIdentifier,
+ const UA_DataSetReaderConfig *config);
+
+/* Get configuration of the dataSetReader */
+UA_StatusCode UA_EXPORT
+UA_Server_DataSetReader_getConfig(UA_Server *server, UA_NodeId dataSetReaderIdentifier,
+ UA_DataSetReaderConfig *config);
+
+/* Get state of DataSetReader */
+UA_StatusCode UA_EXPORT
+UA_Server_DataSetReader_getState(UA_Server *server, UA_NodeId dataSetReaderIdentifier,
+ UA_PubSubState *state);
+
+/**
+ * ReaderGroup
+ * -----------
+
+ * ReaderGroup is used to group a list of DataSetReaders. All ReaderGroups are
+ * created within a PubSubConnection and automatically deleted if the connection
+ * is removed. All network message related filters are only available in the
+ * DataSetReader.
+ *
+ * The RT-levels go along with different requirements. The below listed levels
+ * can be configured for a ReaderGroup.
+ *
+ * - UA_PUBSUB_RT_NONE: RT applied to this level
+ * - PUBSUB_CONFIG_FASTPATH_FIXED_OFFSETS: Extends PubSub RT functionality and
+ * implements fast path message decoding in the Subscriber. Uses a buffered
+ * network message and only decodes the necessary offsets stored in an offset
+ * buffer. */
+
+/* ReaderGroup configuration */
+typedef struct {
+ UA_String name;
+ UA_PubSubSecurityParameters securityParameters;
+ /* PubSub Manager Callback */
+ UA_PubSub_CallbackLifecycle pubsubManagerCallback;
+ /* non std. field */
+ UA_Duration subscribingInterval; // Callback interval for subscriber: set the least publishingInterval value of all DSRs in this RG
+ UA_Boolean enableBlockingSocket; // To enable or disable blocking socket option
+ UA_UInt32 timeout; // Timeout for receive to wait for the packets
+ UA_PubSubRTLevel rtLevel;
+ size_t groupPropertiesSize;
+ UA_KeyValuePair *groupProperties;
+
+ /* Messages are decrypted if a SecurityPolicy is configured and the
+ * securityMode set accordingly. The symmetric key is a runtime information
+ * and has to be set via UA_Server_setReaderGroupEncryptionKey. */
+ UA_MessageSecurityMode securityMode;
+#ifdef UA_ENABLE_PUBSUB_ENCRYPTION
+ UA_PubSubSecurityPolicy *securityPolicy;
+#endif
+} UA_ReaderGroupConfig;
+
+void UA_EXPORT
+UA_ReaderGroupConfig_clear(UA_ReaderGroupConfig *readerGroupConfig);
+
+/* Add DataSetReader to the ReaderGroup */
+UA_StatusCode UA_EXPORT
+UA_Server_addDataSetReader(UA_Server *server, UA_NodeId readerGroupIdentifier,
+ const UA_DataSetReaderConfig *dataSetReaderConfig,
+ UA_NodeId *readerIdentifier);
+
+/* Remove DataSetReader from ReaderGroup */
+UA_StatusCode UA_EXPORT
+UA_Server_removeDataSetReader(UA_Server *server, UA_NodeId readerIdentifier);
+
+/* To Do: Update Configuration of ReaderGroup
+ * UA_StatusCode UA_EXPORT
+ * UA_Server_ReaderGroup_updateConfig(UA_Server *server, UA_NodeId readerGroupIdentifier,
+ * const UA_ReaderGroupConfig *config);
+ */
+
+/* Get configuraiton of ReaderGroup */
+UA_StatusCode UA_EXPORT
+UA_Server_ReaderGroup_getConfig(UA_Server *server, UA_NodeId readerGroupIdentifier,
+ UA_ReaderGroupConfig *config);
+
+/* Get state of ReaderGroup */
+UA_StatusCode UA_EXPORT
+UA_Server_ReaderGroup_getState(UA_Server *server, UA_NodeId readerGroupIdentifier,
+ UA_PubSubState *state);
+
+/* Add ReaderGroup to the created connection */
+UA_StatusCode UA_EXPORT
+UA_Server_addReaderGroup(UA_Server *server, UA_NodeId connectionIdentifier,
+ const UA_ReaderGroupConfig *readerGroupConfig,
+ UA_NodeId *readerGroupIdentifier);
+
+/* Remove ReaderGroup from connection */
+UA_StatusCode UA_EXPORT
+UA_Server_removeReaderGroup(UA_Server *server, UA_NodeId groupIdentifier);
+
+UA_StatusCode UA_EXPORT
+UA_Server_freezeReaderGroupConfiguration(UA_Server *server, const UA_NodeId readerGroupId);
+
+UA_StatusCode UA_EXPORT
+UA_Server_unfreezeReaderGroupConfiguration(UA_Server *server, const UA_NodeId readerGroupId);
+
+UA_StatusCode UA_EXPORT
+UA_Server_setReaderGroupOperational(UA_Server *server, const UA_NodeId readerGroupId);
+
+UA_StatusCode UA_EXPORT
+UA_Server_setReaderGroupDisabled(UA_Server *server, const UA_NodeId readerGroupId);
+
+#ifdef UA_ENABLE_PUBSUB_ENCRYPTION
+/* Set the group key for the message encryption */
+UA_StatusCode UA_EXPORT
+UA_Server_setReaderGroupEncryptionKeys(UA_Server *server, UA_NodeId readerGroup,
+ UA_UInt32 securityTokenId,
+ UA_ByteString signingKey,
+ UA_ByteString encryptingKey,
+ UA_ByteString keyNonce);
+#endif
+
+
+#endif /* UA_ENABLE_PUBSUB */
+
+_UA_END_DECLS
+
+#endif /* UA_SERVER_PUBSUB_H */
+
+/**** amalgamated original file "/include/open62541/server.h" ****/
+
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Copyright 2014-2020 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
+ * Copyright 2015-2016 (c) Sten Grüner
+ * Copyright 2014-2015, 2017 (c) Florian Palm
+ * Copyright 2015-2016 (c) Chris Iatrou
+ * Copyright 2015-2016 (c) Oleksiy Vasylyev
+ * Copyright 2016-2017 (c) Stefan Profanter, fortiss GmbH
* Copyright 2017 (c) Henrik Norrman
* Copyright 2018 (c) Fabian Arndt, Root-Core
- * Copyright 2019 (c) HMS Industrial Networks AB (Author: Jonas Green)
+ * Copyright 2017-2020 (c) HMS Industrial Networks AB (Author: Jonas Green)
+ * Copyright 2020-2021 (c) Christian von Arnim, ISW University of Stuttgart (for VDW and umati)
*/
+
#ifdef UA_ENABLE_PUBSUB
#endif
@@ -27612,12 +27853,32 @@ _UA_END_DECLS
_UA_BEGIN_DECLS
+/* Forward declarations */
+struct UA_PubSubConfiguration;
+typedef struct UA_PubSubConfiguration UA_PubSubConfiguration;
+
+typedef void (*UA_Server_AsyncOperationNotifyCallback)(UA_Server *server);
+
+typedef struct {
+ UA_UInt32 min;
+ UA_UInt32 max;
+} UA_UInt32Range;
+
+typedef struct {
+ UA_Duration min;
+ UA_Duration max;
+} UA_DurationRange;
+
/**
+ * .. _server:
+ *
+ * Server
+ * ======
+ *
* .. _server-configuration:
*
* Server Configuration
* --------------------
-
* The configuration structure is passed to the server during initialization.
* The server expects that the configuration is not modified during runtime.
* Currently, only one server can use a configuration at a time. During
@@ -27634,91 +27895,76 @@ _UA_BEGIN_DECLS
*
* The :ref:`tutorials` provide a good starting point for this. */
-typedef struct {
- UA_UInt32 min;
- UA_UInt32 max;
-} UA_UInt32Range;
-
-typedef struct {
- UA_Duration min;
- UA_Duration max;
-} UA_DurationRange;
-
-#ifdef UA_ENABLE_DISCOVERY
-typedef struct {
-
- /* Timeout in seconds when to automatically remove a registered server from
- * the list, if it doesn't re-register within the given time frame. A value
- * of 0 disables automatic removal. Default is 60 Minutes (60*60). Must be
- * bigger than 10 seconds, because cleanup is only triggered approximately
- * every 10 seconds. The server will still be removed depending on the
- * state of the semaphore file. */
- UA_UInt32 cleanupTimeout;
-
- /* Enable mDNS announce and response to queries */
- bool mdnsEnable;
-
-#ifdef UA_ENABLE_DISCOVERY_MULTICAST
- UA_MdnsDiscoveryConfiguration mdns;
- UA_String mdnsInterfaceIP;
-# if !defined(UA_HAS_GETIFADDR)
- uint32_t *ipAddressList;
- size_t ipAddressListSize;
-# endif
-#endif
-
-} UA_ServerConfig_Discovery;
-
-#endif
-
-typedef void
-(*UA_Server_AsyncOperationNotifyCallback)(UA_Server *server);
-
struct UA_ServerConfig {
- UA_UInt16 nThreads; /* only if multithreading is enabled */
UA_Logger logger;
- /* Server Description:
- * The description must be internally consistent.
- * - The ApplicationUri set in the ApplicationDescription must match the
- * URI set in the server certificate */
+ /**
+ * Server Description
+ * ^^^^^^^^^^^^^^^^^^
+ * The description must be internally consistent. The ApplicationUri set in
+ * the ApplicationDescription must match the URI set in the server
+ * certificate. */
UA_BuildInfo buildInfo;
UA_ApplicationDescription applicationDescription;
UA_ByteString serverCertificate;
- UA_Double shutdownDelay; /* Delay in ms from the shutdown signal (ctrl-c)
- until the actual shutdown. Clients need to be
- able to get a notification ahead of time. */
+ /**
+ * Timeouts and Delays
+ * ^^^^^^^^^^^^^^^^^^^ */
+ /* Delay in ms from the shutdown signal (ctrl-c) until the actual shutdown.
+ * Clients need to be able to get a notification ahead of time. */
+ UA_Double shutdownDelay;
- /* Rule Handling */
- UA_RuleHandling verifyRequestTimestamp; /* Verify that the server sends a
- * timestamp in the request header */
+ /**
+ * Rule Handling
+ * ^^^^^^^^^^^^^
+ * Override the handling of standard-defined behavior. These settings are
+ * used to balance the following contradicting requirements:
+ *
+ * - Strict conformance with the standard (for certification).
+ * - Ensure interoperability with old/non-conforming implementations
+ * encountered in the wild.
+ *
+ * The defaults are set for compatibility with the largest number of OPC UA
+ * vendors (with log warnings activated). Cf. Postel's Law "be conservative
+ * in what you send, be liberal in what you accept".
+ *
+ * See the section :ref:`rule-handling` for the possible settings. */
- /* Custom DataTypes. Attention! Custom datatypes are not cleaned up together
- * with the configuration. So it is possible to allocate them on ROM. */
- const UA_DataTypeArray *customDataTypes;
+ /* Verify that the server sends a timestamp in the request header */
+ UA_RuleHandling verifyRequestTimestamp;
+
+ /* Variables (that don't have a DataType of BaseDataType) must not have an
+ * empty variant value. The default behaviour is to auto-create a matching
+ * zeroed-out value for empty VariableNodes when they are added. */
+ UA_RuleHandling allowEmptyVariables;
/**
- * .. note:: See the section on :ref:`generic-types`. Examples for working
- * with custom data types are provided in
- * ``/examples/custom_datatype/``. */
+ * Custom Data Types
+ * ^^^^^^^^^^^^^^^^^
+ * The following is a linked list of arrays with custom data types. All data
+ * types that are accessible from here are automatically considered for the
+ * decoding of received messages. Custom data types are not cleaned up
+ * together with the configuration. So it is possible to allocate them on
+ * ROM.
+ *
+ * See the section on :ref:`generic-types`. Examples for working with custom
+ * data types are provided in ``/examples/custom_datatype/``. */
+ const UA_DataTypeArray *customDataTypes;
- /* Networking */
+ /**
+ * Networking
+ * ^^^^^^^^^^ */
size_t networkLayersSize;
UA_ServerNetworkLayer *networkLayers;
UA_String customHostname;
-#ifdef UA_ENABLE_PUBSUB
- /*PubSub network layer */
- size_t pubsubTransportLayersSize;
- UA_PubSubTransportLayer *pubsubTransportLayers;
-#endif
-
- /* Available security policies */
+ /**
+ * Security and Encryption
+ * ^^^^^^^^^^^^^^^^^^^^^^^ */
size_t securityPoliciesSize;
UA_SecurityPolicy* securityPolicies;
- /* Available endpoints */
size_t endpointsSize;
UA_EndpointDescription *endpoints;
@@ -27731,44 +27977,33 @@ struct UA_ServerConfig {
* securityPolicies list. */
UA_Boolean securityPolicyNoneDiscoveryOnly;
- /* Node Lifecycle callbacks */
- UA_GlobalNodeLifecycle nodeLifecycle;
+ UA_CertificateVerification certificateVerification;
/**
- * .. note:: See the section for :ref:`node lifecycle
- * handling<node-lifecycle>`. */
-
- /* Access Control */
+ * See the section for :ref:`access-control
+ * handling<access-control>`. */
UA_AccessControl accessControl;
/**
- * .. note:: See the section for :ref:`access-control
- * handling<access-control>`. */
-
- /* Async Operations */
-#if UA_MULTITHREADING >= 100
- UA_Double asyncOperationTimeout; /* in ms, 0 => unlimited */
- size_t maxAsyncOperationQueueSize; /* 0 => unlimited */
- UA_DEPRECATED UA_Double asyncCallRequestTimeout; /* in ms, 0 => unlimited */
- /* Notify workers when an async operation was enqueued */
- UA_Server_AsyncOperationNotifyCallback asyncOperationNotifyCallback;
-#endif
-
- /**
- * .. note:: See the section for :ref:`async
- * operations<async-operations>`. */
-
- /* Nodestore */
+ * Nodes and Node Lifecycle
+ * ^^^^^^^^^^^^^^^^^^^^^^^^
+ * See the section for :ref:`node lifecycle handling<node-lifecycle>`. */
UA_Nodestore nodestore;
+ UA_GlobalNodeLifecycle nodeLifecycle;
- /* Certificate Verification */
- UA_CertificateVerification certificateVerification;
-
- /* Relax constraints for the InformationModel */
- UA_Boolean relaxEmptyValueConstraint; /* Nominally, only variables with data
- * type BaseDataType can have an empty
- * value. */
+ /**
+ * Copy the HasModellingRule reference in instances from the type
+ * definition in UA_Server_addObjectNode and UA_Server_addVariableNode.
+ *
+ * Part 3 - 6.4.4: [...] it is not required that newly created or referenced
+ * instances based on InstanceDeclarations have a ModellingRule, however, it
+ * is allowed that they have any ModellingRule independent of the
+ * ModellingRule of their InstanceDeclaration */
+ UA_Boolean modellingRulesOnInstances;
+ /**
+ * Limits
+ * ^^^^^^ */
/* Limits for SecureChannels */
UA_UInt16 maxSecureChannels;
UA_UInt32 maxSecurityTokenLifetime; /* in ms */
@@ -27790,6 +28025,44 @@ struct UA_ServerConfig {
/* Limits for Requests */
UA_UInt32 maxReferencesPerNode;
+ /**
+ * Async Operations
+ * ^^^^^^^^^^^^^^^^
+ * See the section for :ref:`async operations<async-operations>`. */
+#if UA_MULTITHREADING >= 100
+ UA_Double asyncOperationTimeout; /* in ms, 0 => unlimited */
+ size_t maxAsyncOperationQueueSize; /* 0 => unlimited */
+ /* Notify workers when an async operation was enqueued */
+ UA_Server_AsyncOperationNotifyCallback asyncOperationNotifyCallback;
+#endif
+
+ /**
+ * Discovery
+ * ^^^^^^^^^ */
+#ifdef UA_ENABLE_DISCOVERY
+ /* Timeout in seconds when to automatically remove a registered server from
+ * the list, if it doesn't re-register within the given time frame. A value
+ * of 0 disables automatic removal. Default is 60 Minutes (60*60). Must be
+ * bigger than 10 seconds, because cleanup is only triggered approximately
+ * every 10 seconds. The server will still be removed depending on the
+ * state of the semaphore file. */
+ UA_UInt32 discoveryCleanupTimeout;
+
+# ifdef UA_ENABLE_DISCOVERY_MULTICAST
+ UA_Boolean mdnsEnabled;
+ UA_MdnsDiscoveryConfiguration mdnsConfig;
+ UA_String mdnsInterfaceIP;
+# if !defined(UA_HAS_GETIFADDR)
+ size_t mdnsIpAddressListSize;
+ UA_UInt32 *mdnsIpAddressList;
+# endif
+# endif
+#endif
+
+ /**
+ * Subscriptions
+ * ^^^^^^^^^^^^^ */
+#ifdef UA_ENABLE_SUBSCRIPTIONS
/* Limits for Subscriptions */
UA_UInt32 maxSubscriptions;
UA_UInt32 maxSubscriptionsPerSession;
@@ -27799,9 +28072,9 @@ struct UA_ServerConfig {
UA_UInt32 maxNotificationsPerPublish;
UA_Boolean enableRetransmissionQueue;
UA_UInt32 maxRetransmissionQueueSize; /* 0 -> unlimited size */
-#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
+# ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
UA_UInt32 maxEventsPerNode; /* 0 -> unlimited size */
-#endif
+# endif
/* Limits for MonitoredItems */
UA_UInt32 maxMonitoredItems;
@@ -27812,30 +28085,38 @@ struct UA_ServerConfig {
/* Limits for PublishRequests */
UA_UInt32 maxPublishReqPerSession;
- /* Discovery */
-#ifdef UA_ENABLE_DISCOVERY
- UA_ServerConfig_Discovery discovery;
-#endif
-
-#ifdef UA_ENABLE_SUBSCRIPTIONS
/* Register MonitoredItem in Userland
*
* @param server Allows the access to the server object
* @param sessionId The session id, represented as an node id
- * @param sessionContext An optional pointer to user-defined data for the specific data source
+ * @param sessionContext An optional pointer to user-defined data for the
+ * specific data source
* @param nodeid Id of the node in question
* @param nodeidContext An optional pointer to user-defined data, associated
- * with the node in the nodestore. Note that, if the node has already been removed,
- * this value contains a NULL pointer.
- * @param attributeId Identifies which attribute (value, data type etc.) is monitored
+ * with the node in the nodestore. Note that, if the node has already
+ * been removed, this value contains a NULL pointer.
+ * @param attributeId Identifies which attribute (value, data type etc.) is
+ * monitored
* @param removed Determines if the MonitoredItem was removed or created. */
void (*monitoredItemRegisterCallback)(UA_Server *server,
- const UA_NodeId *sessionId, void *sessionContext,
- const UA_NodeId *nodeId, void *nodeContext,
- UA_UInt32 attibuteId, UA_Boolean removed);
+ const UA_NodeId *sessionId,
+ void *sessionContext,
+ const UA_NodeId *nodeId,
+ void *nodeContext,
+ UA_UInt32 attibuteId,
+ UA_Boolean removed);
+#endif
+
+ /**
+ * PubSub
+ * ^^^^^^ */
+#ifdef UA_ENABLE_PUBSUB
+ UA_PubSubConfiguration pubSubConfig;
#endif
- /* Historical Access */
+ /**
+ * Historical Access
+ * ^^^^^^^^^^^^^^^^^ */
#ifdef UA_ENABLE_HISTORIZING
UA_HistoryDatabase historyDatabase;
@@ -27864,34 +28145,1484 @@ struct UA_ServerConfig {
void UA_EXPORT
UA_ServerConfig_clean(UA_ServerConfig *config);
-/* Set a custom hostname in server configuration */
-UA_EXPORT void
-UA_ServerConfig_setCustomHostname(UA_ServerConfig *config,
- const UA_String customHostname);
+/**
+ * .. _server-lifecycle:
+ *
+ * Server Lifecycle
+ * ---------------- */
+
+/* The method UA_Server_new is defined in server_config_default.h. So default
+ * plugins outside of the core library (for logging, etc) are already available
+ * during the initialization.
+ *
+ * UA_Server UA_EXPORT * UA_Server_new(void);
+ */
+
+/* Creates a new server. Moves the config into the server with a shallow copy.
+ * The config content is cleared together with the server. */
+UA_Server UA_EXPORT *
+UA_Server_newWithConfig(UA_ServerConfig *config);
+
+void UA_EXPORT UA_Server_delete(UA_Server *server);
+
+UA_ServerConfig UA_EXPORT *
+UA_Server_getConfig(UA_Server *server);
+
+/* Runs the main loop of the server. In each iteration, this calls into the
+ * networklayers to see if messages have arrived.
+ *
+ * @param server The server object.
+ * @param running The loop is run as long as *running is true.
+ * Otherwise, the server shuts down.
+ * @return Returns the statuscode of the UA_Server_run_shutdown method */
+UA_StatusCode UA_EXPORT
+UA_Server_run(UA_Server *server, const volatile UA_Boolean *running);
+
+/* The prologue part of UA_Server_run (no need to use if you call
+ * UA_Server_run) */
+UA_StatusCode UA_EXPORT
+UA_Server_run_startup(UA_Server *server);
+
+/* Executes a single iteration of the server's main loop.
+ *
+ * @param server The server object.
+ * @param waitInternal Should we wait for messages in the networklayer?
+ * Otherwise, the timouts for the networklayers are set to zero.
+ * The default max wait time is 50millisec.
+ * @return Returns how long we can wait until the next scheduled
+ * callback (in ms) */
+UA_UInt16 UA_EXPORT
+UA_Server_run_iterate(UA_Server *server, UA_Boolean waitInternal);
+
+/* The epilogue part of UA_Server_run (no need to use if you call
+ * UA_Server_run) */
+UA_StatusCode UA_EXPORT
+UA_Server_run_shutdown(UA_Server *server);
+
+/**
+ * Timed Callbacks
+ * ---------------
+ * Add a callback to the server that is executed at a defined time.
+ * The callback can also be registered with a cyclic interval. */
+
+/* Add a callback for execution at a specified time. If the indicated time lies
+ * in the past, then the callback is executed at the next iteration of the
+ * server's main loop.
+ *
+ * @param server The server object.
+ * @param callback The callback that shall be added.
+ * @param data Data that is forwarded to the callback.
+ * @param date The timestamp for the execution time.
+ * @param callbackId Set to the identifier of the repeated callback . This can
+ * be used to cancel the callback later on. If the pointer is null, the
+ * identifier is not set.
+ * @return Upon success, ``UA_STATUSCODE_GOOD`` is returned. An error code
+ * otherwise. */
+UA_StatusCode UA_EXPORT UA_THREADSAFE
+UA_Server_addTimedCallback(UA_Server *server, UA_ServerCallback callback,
+ void *data, UA_DateTime date, UA_UInt64 *callbackId);
+
+/* Add a callback for cyclic repetition to the server.
+ *
+ * @param server The server object.
+ * @param callback The callback that shall be added.
+ * @param data Data that is forwarded to the callback.
+ * @param interval_ms The callback shall be repeatedly executed with the given
+ * interval (in ms). The interval must be positive. The first execution
+ * occurs at now() + interval at the latest.
+ * @param callbackId Set to the identifier of the repeated callback . This can
+ * be used to cancel the callback later on. If the pointer is null, the
+ * identifier is not set.
+ * @return Upon success, ``UA_STATUSCODE_GOOD`` is returned. An error code
+ * otherwise. */
+UA_StatusCode UA_EXPORT UA_THREADSAFE
+UA_Server_addRepeatedCallback(UA_Server *server, UA_ServerCallback callback,
+ void *data, UA_Double interval_ms,
+ UA_UInt64 *callbackId);
+
+UA_StatusCode UA_EXPORT UA_THREADSAFE
+UA_Server_changeRepeatedCallbackInterval(UA_Server *server, UA_UInt64 callbackId,
+ UA_Double interval_ms);
+
+/* Remove a repeated callback. Does nothing if the callback is not found.
+ *
+ * @param server The server object.
+ * @param callbackId The id of the callback */
+void UA_EXPORT UA_THREADSAFE
+UA_Server_removeCallback(UA_Server *server, UA_UInt64 callbackId);
+
+#define UA_Server_removeRepeatedCallback(server, callbackId) \
+ UA_Server_removeCallback(server, callbackId);
+
+/**
+ * Session Handling
+ * ----------------
+ * A new session is announced via the AccessControl plugin. The session
+ * identifier is forwarded to the relevant callbacks back into userland. The
+ * following methods enable an interaction with a particular session. */
+
+/* Manually close a session */
+UA_EXPORT UA_StatusCode UA_THREADSAFE
+UA_Server_closeSession(UA_Server *server, const UA_NodeId *sessionId);
+
+/* Session Parameters: Besides the user-definable session context pointer,
+ * so-called session parameters are a way to attach key-value parameters to a
+ * session. This enables "plugins" to attach data to a session without impacting
+ * the user-definedable session context pointer. */
+
+UA_EXPORT UA_StatusCode UA_THREADSAFE
+UA_Server_setSessionParameter(UA_Server *server, const UA_NodeId *sessionId,
+ const char *name, const UA_Variant *parameter);
+
+UA_EXPORT void UA_THREADSAFE
+UA_Server_deleteSessionParameter(UA_Server *server, const UA_NodeId *sessionId,
+ const char *name);
+
+/* Returns NULL if the session or the parameter are not defined. Returns a deep
+ * copy otherwise */
+UA_EXPORT UA_StatusCode UA_THREADSAFE
+UA_Server_getSessionParameter(UA_Server *server, const UA_NodeId *sessionId,
+ const char *name, UA_Variant *outParameter);
+
+/* Returns NULL if the parameter is not defined or not of the right datatype */
+UA_EXPORT UA_StatusCode UA_THREADSAFE
+UA_Server_getSessionScalarParameter(UA_Server *server, const UA_NodeId *sessionId,
+ const char *name, const UA_DataType *type,
+ UA_Variant *outParameter);
+
+UA_EXPORT UA_StatusCode UA_THREADSAFE
+UA_Server_getSessionArrayParameter(UA_Server *server, const UA_NodeId *sessionId,
+ const char *name, const UA_DataType *type,
+ UA_Variant *outParameter);
+
+/**
+ * Reading and Writing Node Attributes
+ * -----------------------------------
+ * The functions for reading and writing node attributes call the regular read
+ * and write service in the background that are also used over the network.
+ *
+ * The following attributes cannot be read, since the local "admin" user always
+ * has full rights.
+ *
+ * - UserWriteMask
+ * - UserAccessLevel
+ * - UserExecutable */
+/* Read an attribute of a node. The specialized functions below provide a more
+ * concise syntax.
+ *
+ * @param server The server object.
+ * @param item ReadValueIds contain the NodeId of the target node, the id of the
+ * attribute to read and (optionally) an index range to read parts
+ * of an array only. See the section on NumericRange for the format
+ * used for array ranges.
+ * @param timestamps Which timestamps to return for the attribute.
+ * @return Returns a DataValue that contains either an error code, or a variant
+ * with the attribute value and the timestamps. */
+UA_DataValue UA_EXPORT UA_THREADSAFE
+UA_Server_read(UA_Server *server, const UA_ReadValueId *item,
+ UA_TimestampsToReturn timestamps);
+
+/* Don't use this function. There are typed versions for every supported
+ * attribute. */
+UA_StatusCode UA_EXPORT UA_THREADSAFE
+__UA_Server_read(UA_Server *server, const UA_NodeId *nodeId,
+ UA_AttributeId attributeId, void *v);
+
+static UA_INLINE UA_THREADSAFE UA_StatusCode
+UA_Server_readNodeId(UA_Server *server, const UA_NodeId nodeId,
+ UA_NodeId *outNodeId) {
+ return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_NODEID, outNodeId);
+}
+
+static UA_INLINE UA_THREADSAFE UA_StatusCode
+UA_Server_readNodeClass(UA_Server *server, const UA_NodeId nodeId,
+ UA_NodeClass *outNodeClass) {
+ return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_NODECLASS,
+ outNodeClass);
+}
+
+static UA_INLINE UA_THREADSAFE UA_StatusCode
+UA_Server_readBrowseName(UA_Server *server, const UA_NodeId nodeId,
+ UA_QualifiedName *outBrowseName) {
+ return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_BROWSENAME,
+ outBrowseName);
+}
+
+static UA_INLINE UA_THREADSAFE UA_StatusCode
+UA_Server_readDisplayName(UA_Server *server, const UA_NodeId nodeId,
+ UA_LocalizedText *outDisplayName) {
+ return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_DISPLAYNAME,
+ outDisplayName);
+}
+
+static UA_INLINE UA_THREADSAFE UA_StatusCode
+UA_Server_readDescription(UA_Server *server, const UA_NodeId nodeId,
+ UA_LocalizedText *outDescription) {
+ return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_DESCRIPTION,
+ outDescription);
+}
+
+static UA_INLINE UA_THREADSAFE UA_StatusCode
+UA_Server_readWriteMask(UA_Server *server, const UA_NodeId nodeId,
+ UA_UInt32 *outWriteMask) {
+ return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_WRITEMASK,
+ outWriteMask);
+}
+
+static UA_INLINE UA_THREADSAFE UA_StatusCode
+UA_Server_readIsAbstract(UA_Server *server, const UA_NodeId nodeId,
+ UA_Boolean *outIsAbstract) {
+ return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_ISABSTRACT,
+ outIsAbstract);
+}
+
+static UA_INLINE UA_THREADSAFE UA_StatusCode
+UA_Server_readSymmetric(UA_Server *server, const UA_NodeId nodeId,
+ UA_Boolean *outSymmetric) {
+ return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_SYMMETRIC,
+ outSymmetric);
+}
+
+static UA_INLINE UA_THREADSAFE UA_StatusCode
+UA_Server_readInverseName(UA_Server *server, const UA_NodeId nodeId,
+ UA_LocalizedText *outInverseName) {
+ return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_INVERSENAME,
+ outInverseName);
+}
+
+static UA_INLINE UA_THREADSAFE UA_StatusCode
+UA_Server_readContainsNoLoops(UA_Server *server, const UA_NodeId nodeId,
+ UA_Boolean *outContainsNoLoops) {
+ return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_CONTAINSNOLOOPS,
+ outContainsNoLoops);
+}
+
+static UA_INLINE UA_THREADSAFE UA_StatusCode
+UA_Server_readEventNotifier(UA_Server *server, const UA_NodeId nodeId,
+ UA_Byte *outEventNotifier) {
+ return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_EVENTNOTIFIER,
+ outEventNotifier);
+}
+
+static UA_INLINE UA_THREADSAFE UA_StatusCode
+UA_Server_readValue(UA_Server *server, const UA_NodeId nodeId,
+ UA_Variant *outValue) {
+ return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_VALUE, outValue);
+}
+
+static UA_INLINE UA_THREADSAFE UA_StatusCode
+UA_Server_readDataType(UA_Server *server, const UA_NodeId nodeId,
+ UA_NodeId *outDataType) {
+ return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_DATATYPE,
+ outDataType);
+}
+
+static UA_INLINE UA_THREADSAFE UA_StatusCode
+UA_Server_readValueRank(UA_Server *server, const UA_NodeId nodeId,
+ UA_Int32 *outValueRank) {
+ return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_VALUERANK,
+ outValueRank);
+}
+
+/* Returns a variant with an int32 array */
+static UA_INLINE UA_THREADSAFE UA_StatusCode
+UA_Server_readArrayDimensions(UA_Server *server, const UA_NodeId nodeId,
+ UA_Variant *outArrayDimensions) {
+ return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_ARRAYDIMENSIONS,
+ outArrayDimensions);
+}
+
+static UA_INLINE UA_THREADSAFE UA_StatusCode
+UA_Server_readAccessLevel(UA_Server *server, const UA_NodeId nodeId,
+ UA_Byte *outAccessLevel) {
+ return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_ACCESSLEVEL,
+ outAccessLevel);
+}
+
+static UA_INLINE UA_THREADSAFE UA_StatusCode
+UA_Server_readMinimumSamplingInterval(UA_Server *server, const UA_NodeId nodeId,
+ UA_Double *outMinimumSamplingInterval) {
+ return __UA_Server_read(server, &nodeId,
+ UA_ATTRIBUTEID_MINIMUMSAMPLINGINTERVAL,
+ outMinimumSamplingInterval);
+}
+
+static UA_INLINE UA_THREADSAFE UA_StatusCode
+UA_Server_readHistorizing(UA_Server *server, const UA_NodeId nodeId,
+ UA_Boolean *outHistorizing) {
+ return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_HISTORIZING,
+ outHistorizing);
+}
+
+static UA_INLINE UA_THREADSAFE UA_StatusCode
+UA_Server_readExecutable(UA_Server *server, const UA_NodeId nodeId,
+ UA_Boolean *outExecutable) {
+ return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_EXECUTABLE,
+ outExecutable);
+}
+
+/**
+ * The following node attributes cannot be changed once a node has been created:
+ *
+ * - NodeClass
+ * - NodeId
+ * - Symmetric
+ * - ContainsNoLoops
+ *
+ * The following attributes cannot be written from the server, as they are
+ * specific to the different users and set by the access control callback:
+ *
+ * - UserWriteMask
+ * - UserAccessLevel
+ * - UserExecutable
+ */
+
+/* Overwrite an attribute of a node. The specialized functions below provide a
+ * more concise syntax.
+ *
+ * @param server The server object.
+ * @param value WriteValues contain the NodeId of the target node, the id of the
+ * attribute to overwritten, the actual value and (optionally) an
+ * index range to replace parts of an array only. of an array only.
+ * See the section on NumericRange for the format used for array
+ * ranges.
+ * @return Returns a status code. */
+UA_StatusCode UA_EXPORT UA_THREADSAFE
+UA_Server_write(UA_Server *server, const UA_WriteValue *value);
+
+/* Don't use this function. There are typed versions with no additional
+ * overhead. */
+UA_StatusCode UA_EXPORT UA_THREADSAFE
+__UA_Server_write(UA_Server *server, const UA_NodeId *nodeId,
+ const UA_AttributeId attributeId,
+ const UA_DataType *attr_type, const void *attr);
+
+static UA_INLINE UA_THREADSAFE UA_StatusCode
+UA_Server_writeBrowseName(UA_Server *server, const UA_NodeId nodeId,
+ const UA_QualifiedName browseName) {
+ return __UA_Server_write(server, &nodeId, UA_ATTRIBUTEID_BROWSENAME,
+ &UA_TYPES[UA_TYPES_QUALIFIEDNAME], &browseName);
+}
+
+static UA_INLINE UA_THREADSAFE UA_StatusCode
+UA_Server_writeDisplayName(UA_Server *server, const UA_NodeId nodeId,
+ const UA_LocalizedText displayName) {
+ return __UA_Server_write(server, &nodeId, UA_ATTRIBUTEID_DISPLAYNAME,
+ &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], &displayName);
+}
+
+static UA_INLINE UA_THREADSAFE UA_StatusCode
+UA_Server_writeDescription(UA_Server *server, const UA_NodeId nodeId,
+ const UA_LocalizedText description) {
+ return __UA_Server_write(server, &nodeId, UA_ATTRIBUTEID_DESCRIPTION,
+ &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], &description);
+}
+
+static UA_INLINE UA_THREADSAFE UA_StatusCode
+UA_Server_writeWriteMask(UA_Server *server, const UA_NodeId nodeId,
+ const UA_UInt32 writeMask) {
+ return __UA_Server_write(server, &nodeId, UA_ATTRIBUTEID_WRITEMASK,
+ &UA_TYPES[UA_TYPES_UINT32], &writeMask);
+}
+
+static UA_INLINE UA_THREADSAFE UA_StatusCode
+UA_Server_writeIsAbstract(UA_Server *server, const UA_NodeId nodeId,
+ const UA_Boolean isAbstract) {
+ return __UA_Server_write(server, &nodeId, UA_ATTRIBUTEID_ISABSTRACT,
+ &UA_TYPES[UA_TYPES_BOOLEAN], &isAbstract);
+}
+
+static UA_INLINE UA_THREADSAFE UA_StatusCode
+UA_Server_writeInverseName(UA_Server *server, const UA_NodeId nodeId,
+ const UA_LocalizedText inverseName) {
+ return __UA_Server_write(server, &nodeId, UA_ATTRIBUTEID_INVERSENAME,
+ &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], &inverseName);
+}
+
+static UA_INLINE UA_THREADSAFE UA_StatusCode
+UA_Server_writeEventNotifier(UA_Server *server, const UA_NodeId nodeId,
+ const UA_Byte eventNotifier) {
+ return __UA_Server_write(server, &nodeId, UA_ATTRIBUTEID_EVENTNOTIFIER,
+ &UA_TYPES[UA_TYPES_BYTE], &eventNotifier);
+}
+
+/**
+ * Writes an UA_Variant to a variable/variableType node.
+ * StatusCode is set to ``UA_STATUSCODE_GOOD``, sourceTimestamp and
+ * serverTimestamp are set to UA_DateTime_now()
+ */
+static UA_INLINE UA_THREADSAFE UA_StatusCode
+UA_Server_writeValue(UA_Server *server, const UA_NodeId nodeId,
+ const UA_Variant value) {
+ return __UA_Server_write(server, &nodeId, UA_ATTRIBUTEID_VALUE,
+ &UA_TYPES[UA_TYPES_VARIANT], &value);
+}
+
+/**
+ * Writes an UA_DataValue to a variable/variableType node.
+ * In contrast to UA_Server_writeValue, this functions can also write
+ * sourceTimestamp, serverTimestamp and statusCode.
+ */
+static UA_INLINE UA_THREADSAFE UA_StatusCode
+UA_Server_writeDataValue(UA_Server *server, const UA_NodeId nodeId,
+ const UA_DataValue value) {
+ return __UA_Server_write(server, &nodeId, UA_ATTRIBUTEID_VALUE,
+ &UA_TYPES[UA_TYPES_DATAVALUE], &value);
+}
+
+static UA_INLINE UA_THREADSAFE UA_StatusCode
+UA_Server_writeDataType(UA_Server *server, const UA_NodeId nodeId,
+ const UA_NodeId dataType) {
+ return __UA_Server_write(server, &nodeId, UA_ATTRIBUTEID_DATATYPE,
+ &UA_TYPES[UA_TYPES_NODEID], &dataType);
+}
+
+static UA_INLINE UA_THREADSAFE UA_StatusCode
+UA_Server_writeValueRank(UA_Server *server, const UA_NodeId nodeId,
+ const UA_Int32 valueRank) {
+ return __UA_Server_write(server, &nodeId, UA_ATTRIBUTEID_VALUERANK,
+ &UA_TYPES[UA_TYPES_INT32], &valueRank);
+}
+
+static UA_INLINE UA_THREADSAFE UA_StatusCode
+UA_Server_writeArrayDimensions(UA_Server *server, const UA_NodeId nodeId,
+ const UA_Variant arrayDimensions) {
+ return __UA_Server_write(server, &nodeId, UA_ATTRIBUTEID_ARRAYDIMENSIONS,
+ &UA_TYPES[UA_TYPES_VARIANT], &arrayDimensions);
+}
+
+static UA_INLINE UA_THREADSAFE UA_StatusCode
+UA_Server_writeAccessLevel(UA_Server *server, const UA_NodeId nodeId,
+ const UA_Byte accessLevel) {
+ return __UA_Server_write(server, &nodeId, UA_ATTRIBUTEID_ACCESSLEVEL,
+ &UA_TYPES[UA_TYPES_BYTE], &accessLevel);
+}
+
+static UA_INLINE UA_THREADSAFE UA_StatusCode
+UA_Server_writeMinimumSamplingInterval(UA_Server *server, const UA_NodeId nodeId,
+ const UA_Double miniumSamplingInterval) {
+ return __UA_Server_write(server, &nodeId,
+ UA_ATTRIBUTEID_MINIMUMSAMPLINGINTERVAL,
+ &UA_TYPES[UA_TYPES_DOUBLE],
+ &miniumSamplingInterval);
+}
+
+static UA_INLINE UA_THREADSAFE UA_StatusCode
+UA_Server_writeHistorizing(UA_Server *server, const UA_NodeId nodeId,
+ const UA_Boolean historizing) {
+ return __UA_Server_write(server, &nodeId,
+ UA_ATTRIBUTEID_HISTORIZING,
+ &UA_TYPES[UA_TYPES_BOOLEAN],
+ &historizing);
+}
+
+static UA_INLINE UA_THREADSAFE UA_StatusCode
+UA_Server_writeExecutable(UA_Server *server, const UA_NodeId nodeId,
+ const UA_Boolean executable) {
+ return __UA_Server_write(server, &nodeId, UA_ATTRIBUTEID_EXECUTABLE,
+ &UA_TYPES[UA_TYPES_BOOLEAN], &executable); }
+
+/**
+ * Browsing
+ * -------- */
+
+/* Browse the references of a particular node. See the definition of
+ * BrowseDescription structure for details. */
+UA_BrowseResult UA_EXPORT UA_THREADSAFE
+UA_Server_browse(UA_Server *server, UA_UInt32 maxReferences,
+ const UA_BrowseDescription *bd);
+
+UA_BrowseResult UA_EXPORT UA_THREADSAFE
+UA_Server_browseNext(UA_Server *server, UA_Boolean releaseContinuationPoint,
+ const UA_ByteString *continuationPoint);
+
+/* Non-standard version of the Browse service that recurses into child nodes.
+ *
+ * Possible loops (that can occur for non-hierarchical references) are handled
+ * internally. Every node is added at most once to the results array.
+ *
+ * Nodes are only added if they match the NodeClassMask in the
+ * BrowseDescription. However, child nodes are still recursed into if the
+ * NodeClass does not match. So it is possible, for example, to get all
+ * VariableNodes below a certain ObjectNode, with additional objects in the
+ * hierarchy below. */
+UA_StatusCode UA_EXPORT UA_THREADSAFE
+UA_Server_browseRecursive(UA_Server *server, const UA_BrowseDescription *bd,
+ size_t *resultsSize, UA_ExpandedNodeId **results);
+
+UA_BrowsePathResult UA_EXPORT UA_THREADSAFE
+UA_Server_translateBrowsePathToNodeIds(UA_Server *server,
+ const UA_BrowsePath *browsePath);
+
+/* A simplified TranslateBrowsePathsToNodeIds based on the
+ * SimpleAttributeOperand type (Part 4, 7.4.4.5).
+ *
+ * This specifies a relative path using a list of BrowseNames instead of the
+ * RelativePath structure. The list of BrowseNames is equivalent to a
+ * RelativePath that specifies forward references which are subtypes of the
+ * HierarchicalReferences ReferenceType. All Nodes followed by the browsePath
+ * shall be of the NodeClass Object or Variable. */
+UA_BrowsePathResult UA_EXPORT UA_THREADSAFE
+UA_Server_browseSimplifiedBrowsePath(UA_Server *server, const UA_NodeId origin,
+ size_t browsePathSize,
+ const UA_QualifiedName *browsePath);
+
+#ifndef HAVE_NODEITER_CALLBACK
+#define HAVE_NODEITER_CALLBACK
+/* Iterate over all nodes referenced by parentNodeId by calling the callback
+ * function for each child node (in ifdef because GCC/CLANG handle include order
+ * differently) */
+typedef UA_StatusCode
+(*UA_NodeIteratorCallback)(UA_NodeId childId, UA_Boolean isInverse,
+ UA_NodeId referenceTypeId, void *handle);
+#endif
+
+UA_StatusCode UA_EXPORT UA_THREADSAFE
+UA_Server_forEachChildNodeCall(UA_Server *server, UA_NodeId parentNodeId,
+ UA_NodeIteratorCallback callback, void *handle);
+
+#ifdef UA_ENABLE_DISCOVERY
+
+/**
+ * Discovery
+ * --------- */
+/* Register the given server instance at the discovery server.
+ * This should be called periodically.
+ * The semaphoreFilePath is optional. If the given file is deleted,
+ * the server will automatically be unregistered. This could be
+ * for example a pid file which is deleted if the server crashes.
+ *
+ * When the server shuts down you need to call unregister.
+ *
+ * @param server
+ * @param client the client which is used to call the RegisterServer. It must
+ * already be connected to the correct endpoint
+ * @param semaphoreFilePath optional parameter pointing to semaphore file. */
+UA_StatusCode UA_EXPORT UA_THREADSAFE
+UA_Server_register_discovery(UA_Server *server, struct UA_Client *client,
+ const char* semaphoreFilePath);
+
+/* Unregister the given server instance from the discovery server.
+ * This should only be called when the server is shutting down.
+ * @param server
+ * @param client the client which is used to call the RegisterServer. It must
+ * already be connected to the correct endpoint */
+UA_StatusCode UA_EXPORT UA_THREADSAFE
+UA_Server_unregister_discovery(UA_Server *server, struct UA_Client *client);
+
+ /* Adds a periodic callback to register the server with the LDS (local
+ * discovery server) periodically. The interval between each register call is
+ * given as second parameter. It should be 10 minutes by default (=
+ * 10*60*1000).
+ *
+ * The delayFirstRegisterMs parameter indicates the delay for the first
+ * register call. If it is 0, the first register call will be after intervalMs
+ * milliseconds, otherwise the server's first register will be after
+ * delayFirstRegisterMs.
+ *
+ * When you manually unregister the server, you also need to cancel the
+ * periodic callback, otherwise it will be automatically be registered again.
+ *
+ * If you call this method multiple times for the same discoveryServerUrl, the
+ * older periodic callback will be removed.
+ *
+ * @param server
+ * @param client the client which is used to call the RegisterServer. It must
+ * not yet be connected and will be connected for every register call
+ * to the given discoveryServerUrl.
+ * @param discoveryServerUrl where this server should register itself. The
+ * string will be copied internally. Therefore you can free it after
+ * calling this method.
+ * @param intervalMs
+ * @param delayFirstRegisterMs
+ * @param periodicCallbackId */
+UA_StatusCode UA_EXPORT UA_THREADSAFE
+UA_Server_addPeriodicServerRegisterCallback(UA_Server *server,
+ struct UA_Client *client,
+ const char* discoveryServerUrl,
+ UA_Double intervalMs,
+ UA_Double delayFirstRegisterMs,
+ UA_UInt64 *periodicCallbackId);
+
+/* Callback for RegisterServer. Data is passed from the register call */
+typedef void
+(*UA_Server_registerServerCallback)(const UA_RegisteredServer *registeredServer,
+ void* data);
+
+/* Set the callback which is called if another server registeres or unregisters
+ * with this instance. This callback is called every time the server gets a
+ * register call. This especially means that for every periodic server register
+ * the callback will be called.
+ *
+ * @param server
+ * @param cb the callback
+ * @param data data passed to the callback
+ * @return ``UA_STATUSCODE_SUCCESS`` on success */
+void UA_EXPORT UA_THREADSAFE
+UA_Server_setRegisterServerCallback(UA_Server *server,
+ UA_Server_registerServerCallback cb, void* data);
+
+#ifdef UA_ENABLE_DISCOVERY_MULTICAST
+
+/* Callback for server detected through mDNS. Data is passed from the register
+ * call
+ *
+ * @param isServerAnnounce indicates if the server has just been detected. If
+ * set to false, this means the server is shutting down.
+ * @param isTxtReceived indicates if we already received the corresponding TXT
+ * record with the path and caps data */
+typedef void
+(*UA_Server_serverOnNetworkCallback)(const UA_ServerOnNetwork *serverOnNetwork,
+ UA_Boolean isServerAnnounce,
+ UA_Boolean isTxtReceived, void* data);
+
+/* Set the callback which is called if another server is found through mDNS or
+ * deleted. It will be called for any mDNS message from the remote server, thus
+ * it may be called multiple times for the same instance. Also the SRV and TXT
+ * records may arrive later, therefore for the first call the server
+ * capabilities may not be set yet. If called multiple times, previous data will
+ * be overwritten.
+ *
+ * @param server
+ * @param cb the callback
+ * @param data data passed to the callback
+ * @return ``UA_STATUSCODE_SUCCESS`` on success */
+void UA_EXPORT UA_THREADSAFE
+UA_Server_setServerOnNetworkCallback(UA_Server *server,
+ UA_Server_serverOnNetworkCallback cb,
+ void* data);
+
+#endif /* UA_ENABLE_DISCOVERY_MULTICAST */
+
+#endif /* UA_ENABLE_DISCOVERY */
+
+/**
+ * Information Model Callbacks
+ * ---------------------------
+ *
+ * There are three places where a callback from an information model to
+ * user-defined code can happen.
+ *
+ * - Custom node constructors and destructors
+ * - Linking VariableNodes with an external data source
+ * - MethodNode callbacks
+ */
+
+void UA_EXPORT
+UA_Server_setAdminSessionContext(UA_Server *server,
+ void *context);
+
+UA_StatusCode UA_EXPORT UA_THREADSAFE
+UA_Server_setNodeTypeLifecycle(UA_Server *server, UA_NodeId nodeId,
+ UA_NodeTypeLifecycle lifecycle);
+
+UA_StatusCode UA_EXPORT UA_THREADSAFE
+UA_Server_getNodeContext(UA_Server *server, UA_NodeId nodeId,
+ void **nodeContext);
+
+/* Careful! The user has to ensure that the destructor callbacks still work. */
+UA_StatusCode UA_EXPORT UA_THREADSAFE
+UA_Server_setNodeContext(UA_Server *server, UA_NodeId nodeId,
+ void *nodeContext);
+
+/**
+ * .. _datasource:
+ *
+ * Data Source Callback
+ * ^^^^^^^^^^^^^^^^^^^^
+ *
+ * The server has a unique way of dealing with the content of variables. Instead
+ * of storing a variant attached to the variable node, the node can point to a
+ * function with a local data provider. Whenever the value attribute is read,
+ * the function will be called and asked to provide a UA_DataValue return value
+ * that contains the value content and additional timestamps.
+ *
+ * It is expected that the read callback is implemented. The write callback can
+ * be set to a null-pointer. */
+
+UA_StatusCode UA_EXPORT UA_THREADSAFE
+UA_Server_setVariableNode_dataSource(UA_Server *server, const UA_NodeId nodeId,
+ const UA_DataSource dataSource);
+
+UA_StatusCode UA_EXPORT UA_THREADSAFE
+UA_Server_setVariableNode_valueCallback(UA_Server *server,
+ const UA_NodeId nodeId,
+ const UA_ValueCallback callback);
+
+UA_StatusCode UA_EXPORT UA_THREADSAFE
+UA_Server_setVariableNode_valueBackend(UA_Server *server,
+ const UA_NodeId nodeId,
+ const UA_ValueBackend valueBackend);
+
+/**
+ * .. _local-monitoreditems:
+ *
+ * Local MonitoredItems
+ * ^^^^^^^^^^^^^^^^^^^^
+ *
+ * MonitoredItems are used with the Subscription mechanism of OPC UA to
+ * transported notifications for data changes and events. MonitoredItems can
+ * also be registered locally. Notifications are then forwarded to a
+ * user-defined callback instead of a remote client. */
+
+#ifdef UA_ENABLE_SUBSCRIPTIONS
+
+typedef void (*UA_Server_DataChangeNotificationCallback)
+ (UA_Server *server, UA_UInt32 monitoredItemId, void *monitoredItemContext,
+ const UA_NodeId *nodeId, void *nodeContext, UA_UInt32 attributeId,
+ const UA_DataValue *value);
+
+typedef void (*UA_Server_EventNotificationCallback)
+ (UA_Server *server, UA_UInt32 monId, void *monContext,
+ size_t nEventFields, const UA_Variant *eventFields);
+
+/* Create a local MonitoredItem with a sampling interval that detects data
+ * changes.
+ *
+ * @param server The server executing the MonitoredItem
+ * @timestampsToReturn Shall timestamps be added to the value for the callback?
+ * @item The parameters of the new MonitoredItem. Note that the attribute of the
+ * ReadValueId (the node that is monitored) can not be
+ * ``UA_ATTRIBUTEID_EVENTNOTIFIER``. A different callback type needs to be
+ * registered for event notifications.
+ * @monitoredItemContext A pointer that is forwarded with the callback
+ * @callback The callback that is executed on detected data changes
+ *
+ * @return Returns a description of the created MonitoredItem. The structure
+ * also contains a StatusCode (in case of an error) and the identifier of the
+ * new MonitoredItem. */
+UA_MonitoredItemCreateResult UA_EXPORT UA_THREADSAFE
+UA_Server_createDataChangeMonitoredItem(UA_Server *server,
+ UA_TimestampsToReturn timestampsToReturn,
+ const UA_MonitoredItemCreateRequest item,
+ void *monitoredItemContext,
+ UA_Server_DataChangeNotificationCallback callback);
+
+/* UA_MonitoredItemCreateResult UA_EXPORT */
+/* UA_Server_createEventMonitoredItem(UA_Server *server, */
+/* UA_TimestampsToReturn timestampsToReturn, */
+/* const UA_MonitoredItemCreateRequest item, void *context, */
+/* UA_Server_EventNotificationCallback callback); */
+
+UA_StatusCode UA_EXPORT UA_THREADSAFE
+UA_Server_deleteMonitoredItem(UA_Server *server, UA_UInt32 monitoredItemId);
+
+#endif
+
+/**
+ * Method Callbacks
+ * ^^^^^^^^^^^^^^^^
+ * Method callbacks are set to `NULL` (not executable) when a method node is
+ * added over the network. In theory, it is possible to add a callback via
+ * ``UA_Server_setMethodNode_callback`` within the global constructor when
+ * adding methods over the network is really wanted. See the Section
+ * :ref:`object-interaction` for calling methods on an object. */
+
+#ifdef UA_ENABLE_METHODCALLS
+UA_StatusCode UA_EXPORT UA_THREADSAFE
+UA_Server_setMethodNodeCallback(UA_Server *server,
+ const UA_NodeId methodNodeId,
+ UA_MethodCallback methodCallback);
+
+/* Backwards compatibility definition */
+#define UA_Server_setMethodNode_callback(server, methodNodeId, methodCallback) \
+ UA_Server_setMethodNodeCallback(server, methodNodeId, methodCallback)
+
+UA_StatusCode UA_EXPORT UA_THREADSAFE
+UA_Server_getMethodNodeCallback(UA_Server *server,
+ const UA_NodeId methodNodeId,
+ UA_MethodCallback *outMethodCallback);
+
+UA_CallMethodResult UA_EXPORT UA_THREADSAFE
+UA_Server_call(UA_Server *server, const UA_CallMethodRequest *request);
+#endif
+
+/**
+ * .. _object-interaction:
+ *
+ * Interacting with Objects
+ * ------------------------
+ * Objects in the information model are represented as ObjectNodes. Some
+ * convenience functions are provided to simplify the interaction with objects.
+ */
+
+/* Write an object property. The property is represented as a VariableNode with
+ * a ``HasProperty`` reference from the ObjectNode. The VariableNode is
+ * identified by its BrowseName. Writing the property sets the value attribute
+ * of the VariableNode.
+ *
+ * @param server The server object
+ * @param objectId The identifier of the object (node)
+ * @param propertyName The name of the property
+ * @param value The value to be set for the event attribute
+ * @return The StatusCode for setting the event attribute */
+UA_StatusCode UA_EXPORT UA_THREADSAFE
+UA_Server_writeObjectProperty(UA_Server *server, const UA_NodeId objectId,
+ const UA_QualifiedName propertyName,
+ const UA_Variant value);
+
+/* Directly point to the scalar value instead of a variant */
+UA_StatusCode UA_EXPORT UA_THREADSAFE
+UA_Server_writeObjectProperty_scalar(UA_Server *server, const UA_NodeId objectId,
+ const UA_QualifiedName propertyName,
+ const void *value, const UA_DataType *type);
+
+/* Read an object property.
+ *
+ * @param server The server object
+ * @param objectId The identifier of the object (node)
+ * @param propertyName The name of the property
+ * @param value Contains the property value after reading. Must not be NULL.
+ * @return The StatusCode for setting the event attribute */
+UA_StatusCode UA_EXPORT UA_THREADSAFE
+UA_Server_readObjectProperty(UA_Server *server, const UA_NodeId objectId,
+ const UA_QualifiedName propertyName,
+ UA_Variant *value);
+
+/**
+ * .. _addnodes:
+ *
+ * Node Addition and Deletion
+ * --------------------------
+ * When creating dynamic node instances at runtime, chances are that you will
+ * not care about the specific NodeId of the new node, as long as you can
+ * reference it later. When passing numeric NodeIds with a numeric identifier 0,
+ * the stack evaluates this as "select a random unassigned numeric NodeId in
+ * that namespace". To find out which NodeId was actually assigned to the new
+ * node, you may pass a pointer `outNewNodeId`, which will (after a successful
+ * node insertion) contain the nodeId of the new node. You may also pass a
+ * ``NULL`` pointer if this result is not needed.
+ *
+ * See the Section :ref:`node-lifecycle` on constructors and on attaching
+ * user-defined data to nodes.
+ *
+ * The methods for node addition and deletion take mostly const arguments that
+ * are not modified. When creating a node, a deep copy of the node identifier,
+ * node attributes, etc. is created. Therefore, it is possible to call for
+ * example ``UA_Server_addVariablenode`` with a value attribute (a
+ * :ref:`variant`) pointing to a memory location on the stack. If you need
+ * changes to a variable value to manifest at a specific memory location, please
+ * use a :ref:`datasource` or a :ref:`value-callback`. */
+
+/* Protect against redundant definitions for server/client */
+#ifndef UA_DEFAULT_ATTRIBUTES_DEFINED
+#define UA_DEFAULT_ATTRIBUTES_DEFINED
+/* The default for variables is "BaseDataType" for the datatype, -2 for the
+ * valuerank and a read-accesslevel. */
+UA_EXPORT extern const UA_VariableAttributes UA_VariableAttributes_default;
+UA_EXPORT extern const UA_VariableTypeAttributes UA_VariableTypeAttributes_default;
+/* Methods are executable by default */
+UA_EXPORT extern const UA_MethodAttributes UA_MethodAttributes_default;
+/* The remaining attribute definitions are currently all zeroed out */
+UA_EXPORT extern const UA_ObjectAttributes UA_ObjectAttributes_default;
+UA_EXPORT extern const UA_ObjectTypeAttributes UA_ObjectTypeAttributes_default;
+UA_EXPORT extern const UA_ReferenceTypeAttributes UA_ReferenceTypeAttributes_default;
+UA_EXPORT extern const UA_DataTypeAttributes UA_DataTypeAttributes_default;
+UA_EXPORT extern const UA_ViewAttributes UA_ViewAttributes_default;
+#endif
+
+/* Don't use this function. There are typed versions as inline functions. */
+UA_StatusCode UA_EXPORT UA_THREADSAFE
+__UA_Server_addNode(UA_Server *server, const UA_NodeClass nodeClass,
+ const UA_NodeId *requestedNewNodeId,
+ const UA_NodeId *parentNodeId,
+ const UA_NodeId *referenceTypeId,
+ const UA_QualifiedName browseName,
+ const UA_NodeId *typeDefinition,
+ const UA_NodeAttributes *attr,
+ const UA_DataType *attributeType,
+ void *nodeContext, UA_NodeId *outNewNodeId);
+
+static UA_INLINE UA_THREADSAFE UA_StatusCode
+UA_Server_addVariableNode(UA_Server *server, const UA_NodeId requestedNewNodeId,
+ const UA_NodeId parentNodeId,
+ const UA_NodeId referenceTypeId,
+ const UA_QualifiedName browseName,
+ const UA_NodeId typeDefinition,
+ const UA_VariableAttributes attr,
+ void *nodeContext, UA_NodeId *outNewNodeId) {
+ return __UA_Server_addNode(server, UA_NODECLASS_VARIABLE, &requestedNewNodeId,
+ &parentNodeId, &referenceTypeId, browseName,
+ &typeDefinition, (const UA_NodeAttributes*)&attr,
+ &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],
+ nodeContext, outNewNodeId);
+}
+
+static UA_INLINE UA_THREADSAFE UA_StatusCode
+UA_Server_addVariableTypeNode(UA_Server *server,
+ const UA_NodeId requestedNewNodeId,
+ const UA_NodeId parentNodeId,
+ const UA_NodeId referenceTypeId,
+ const UA_QualifiedName browseName,
+ const UA_NodeId typeDefinition,
+ const UA_VariableTypeAttributes attr,
+ void *nodeContext, UA_NodeId *outNewNodeId) {
+ return __UA_Server_addNode(server, UA_NODECLASS_VARIABLETYPE,
+ &requestedNewNodeId, &parentNodeId, &referenceTypeId,
+ browseName, &typeDefinition,
+ (const UA_NodeAttributes*)&attr,
+ &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES],
+ nodeContext, outNewNodeId);
+}
+
+static UA_INLINE UA_THREADSAFE UA_StatusCode
+UA_Server_addObjectNode(UA_Server *server, const UA_NodeId requestedNewNodeId,
+ const UA_NodeId parentNodeId,
+ const UA_NodeId referenceTypeId,
+ const UA_QualifiedName browseName,
+ const UA_NodeId typeDefinition,
+ const UA_ObjectAttributes attr,
+ void *nodeContext, UA_NodeId *outNewNodeId) {
+ return __UA_Server_addNode(server, UA_NODECLASS_OBJECT, &requestedNewNodeId,
+ &parentNodeId, &referenceTypeId, browseName,
+ &typeDefinition, (const UA_NodeAttributes*)&attr,
+ &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],
+ nodeContext, outNewNodeId);
+}
+
+static UA_INLINE UA_THREADSAFE UA_StatusCode
+UA_Server_addObjectTypeNode(UA_Server *server, const UA_NodeId requestedNewNodeId,
+ const UA_NodeId parentNodeId,
+ const UA_NodeId referenceTypeId,
+ const UA_QualifiedName browseName,
+ const UA_ObjectTypeAttributes attr,
+ void *nodeContext, UA_NodeId *outNewNodeId) {
+ return __UA_Server_addNode(server, UA_NODECLASS_OBJECTTYPE, &requestedNewNodeId,
+ &parentNodeId, &referenceTypeId, browseName,
+ &UA_NODEID_NULL, (const UA_NodeAttributes*)&attr,
+ &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],
+ nodeContext, outNewNodeId);
+}
+
+static UA_INLINE UA_THREADSAFE UA_StatusCode
+UA_Server_addViewNode(UA_Server *server, const UA_NodeId requestedNewNodeId,
+ const UA_NodeId parentNodeId,
+ const UA_NodeId referenceTypeId,
+ const UA_QualifiedName browseName,
+ const UA_ViewAttributes attr,
+ void *nodeContext, UA_NodeId *outNewNodeId) {
+ return __UA_Server_addNode(server, UA_NODECLASS_VIEW, &requestedNewNodeId,
+ &parentNodeId, &referenceTypeId, browseName,
+ &UA_NODEID_NULL, (const UA_NodeAttributes*)&attr,
+ &UA_TYPES[UA_TYPES_VIEWATTRIBUTES],
+ nodeContext, outNewNodeId);
+}
+
+static UA_INLINE UA_THREADSAFE UA_StatusCode
+UA_Server_addReferenceTypeNode(UA_Server *server,
+ const UA_NodeId requestedNewNodeId,
+ const UA_NodeId parentNodeId,
+ const UA_NodeId referenceTypeId,
+ const UA_QualifiedName browseName,
+ const UA_ReferenceTypeAttributes attr,
+ void *nodeContext, UA_NodeId *outNewNodeId) {
+ return __UA_Server_addNode(server, UA_NODECLASS_REFERENCETYPE,
+ &requestedNewNodeId, &parentNodeId, &referenceTypeId,
+ browseName, &UA_NODEID_NULL,
+ (const UA_NodeAttributes*)&attr,
+ &UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES],
+ nodeContext, outNewNodeId);
+}
+
+static UA_INLINE UA_THREADSAFE UA_StatusCode
+UA_Server_addDataTypeNode(UA_Server *server,
+ const UA_NodeId requestedNewNodeId,
+ const UA_NodeId parentNodeId,
+ const UA_NodeId referenceTypeId,
+ const UA_QualifiedName browseName,
+ const UA_DataTypeAttributes attr,
+ void *nodeContext, UA_NodeId *outNewNodeId) {
+ return __UA_Server_addNode(server, UA_NODECLASS_DATATYPE, &requestedNewNodeId,
+ &parentNodeId, &referenceTypeId, browseName,
+ &UA_NODEID_NULL, (const UA_NodeAttributes*)&attr,
+ &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],
+ nodeContext, outNewNodeId);
+}
+
+UA_StatusCode UA_EXPORT UA_THREADSAFE
+UA_Server_addDataSourceVariableNode(UA_Server *server,
+ const UA_NodeId requestedNewNodeId,
+ const UA_NodeId parentNodeId,
+ const UA_NodeId referenceTypeId,
+ const UA_QualifiedName browseName,
+ const UA_NodeId typeDefinition,
+ const UA_VariableAttributes attr,
+ const UA_DataSource dataSource,
+ void *nodeContext, UA_NodeId *outNewNodeId);
+
+#ifdef UA_ENABLE_METHODCALLS
+
+UA_StatusCode UA_EXPORT UA_THREADSAFE
+UA_Server_addMethodNodeEx(UA_Server *server, const UA_NodeId requestedNewNodeId,
+ const UA_NodeId parentNodeId,
+ const UA_NodeId referenceTypeId,
+ const UA_QualifiedName browseName,
+ const UA_MethodAttributes attr, UA_MethodCallback method,
+ size_t inputArgumentsSize, const UA_Argument *inputArguments,
+ const UA_NodeId inputArgumentsRequestedNewNodeId,
+ UA_NodeId *inputArgumentsOutNewNodeId,
+ size_t outputArgumentsSize, const UA_Argument *outputArguments,
+ const UA_NodeId outputArgumentsRequestedNewNodeId,
+ UA_NodeId *outputArgumentsOutNewNodeId,
+ void *nodeContext, UA_NodeId *outNewNodeId);
+
+static UA_INLINE UA_THREADSAFE UA_StatusCode
+UA_Server_addMethodNode(UA_Server *server, const UA_NodeId requestedNewNodeId,
+ const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId,
+ const UA_QualifiedName browseName, const UA_MethodAttributes attr,
+ UA_MethodCallback method,
+ size_t inputArgumentsSize, const UA_Argument *inputArguments,
+ size_t outputArgumentsSize, const UA_Argument *outputArguments,
+ void *nodeContext, UA_NodeId *outNewNodeId) {
+ return UA_Server_addMethodNodeEx(server, requestedNewNodeId, parentNodeId,
+ referenceTypeId, browseName, attr, method,
+ inputArgumentsSize, inputArguments,
+ UA_NODEID_NULL, NULL,
+ outputArgumentsSize, outputArguments,
+ UA_NODEID_NULL, NULL,
+ nodeContext, outNewNodeId);
+}
+
+#endif
+
+
+/**
+ * The method pair UA_Server_addNode_begin and _finish splits the AddNodes
+ * service in two parts. This is useful if the node shall be modified before
+ * finish the instantiation. For example to add children with specific NodeIds.
+ * Otherwise, mandatory children (e.g. of an ObjectType) are added with
+ * pseudo-random unique NodeIds. Existing children are detected during the
+ * _finish part via their matching BrowseName.
+ *
+ * The _begin method:
+ * - prepares the node and adds it to the nodestore
+ * - copies some unassigned attributes from the TypeDefinition node internally
+ * - adds the references to the parent (and the TypeDefinition if applicable)
+ * - performs type-checking of variables.
+ *
+ * You can add an object node without a parent if you set the parentNodeId and
+ * referenceTypeId to UA_NODE_ID_NULL. Then you need to add the parent reference
+ * and hasTypeDef reference yourself before calling the _finish method.
+ * Not that this is only allowed for object nodes.
+ *
+ * The _finish method:
+ * - copies mandatory children
+ * - calls the node constructor(s) at the end
+ * - may remove the node if it encounters an error.
+ *
+ * The special UA_Server_addMethodNode_finish method needs to be used for method
+ * nodes, since there you need to explicitly specifiy the input and output
+ * arguments which are added in the finish step (if not yet already there) */
+
+/* The ``attr`` argument must have a type according to the NodeClass.
+ * ``VariableAttributes`` for variables, ``ObjectAttributes`` for objects, and
+ * so on. Missing attributes are taken from the TypeDefinition node if
+ * applicable. */
+UA_StatusCode UA_EXPORT UA_THREADSAFE
+UA_Server_addNode_begin(UA_Server *server, const UA_NodeClass nodeClass,
+ const UA_NodeId requestedNewNodeId,
+ const UA_NodeId parentNodeId,
+ const UA_NodeId referenceTypeId,
+ const UA_QualifiedName browseName,
+ const UA_NodeId typeDefinition,
+ const void *attr, const UA_DataType *attributeType,
+ void *nodeContext, UA_NodeId *outNewNodeId);
+
+UA_StatusCode UA_EXPORT UA_THREADSAFE
+UA_Server_addNode_finish(UA_Server *server, const UA_NodeId nodeId);
+
+#ifdef UA_ENABLE_METHODCALLS
+
+UA_StatusCode UA_EXPORT UA_THREADSAFE
+UA_Server_addMethodNode_finish(UA_Server *server, const UA_NodeId nodeId,
+ UA_MethodCallback method,
+ size_t inputArgumentsSize, const UA_Argument *inputArguments,
+ size_t outputArgumentsSize, const UA_Argument *outputArguments);
+
+#endif
+
+/* Deletes a node and optionally all references leading to the node. */
+UA_StatusCode UA_EXPORT UA_THREADSAFE
+UA_Server_deleteNode(UA_Server *server, const UA_NodeId nodeId,
+ UA_Boolean deleteReferences);
+
+/**
+ * Reference Management
+ * -------------------- */
+UA_StatusCode UA_EXPORT UA_THREADSAFE
+UA_Server_addReference(UA_Server *server, const UA_NodeId sourceId,
+ const UA_NodeId refTypeId,
+ const UA_ExpandedNodeId targetId, UA_Boolean isForward);
+
+UA_StatusCode UA_EXPORT UA_THREADSAFE
+UA_Server_deleteReference(UA_Server *server, const UA_NodeId sourceNodeId,
+ const UA_NodeId referenceTypeId, UA_Boolean isForward,
+ const UA_ExpandedNodeId targetNodeId,
+ UA_Boolean deleteBidirectional);
+
+/**
+ * .. _events:
+ *
+ * Events
+ * ------
+ * The method ``UA_Server_createEvent`` creates an event and represents it as
+ * node. The node receives a unique `EventId` which is automatically added to
+ * the node. The method returns a `NodeId` to the object node which represents
+ * the event through ``outNodeId``. The `NodeId` can be used to set the
+ * attributes of the event. The generated `NodeId` is always numeric.
+ * ``outNodeId`` cannot be ``NULL``.
+ *
+ * Note: In order to see an event in UAExpert, the field `Time` must be given a
+ * value!
+ *
+ * The method ``UA_Server_triggerEvent`` "triggers" an event by adding it to all
+ * monitored items of the specified origin node and those of all its parents.
+ * Any filters specified by the monitored items are automatically applied. Using
+ * this method deletes the node generated by ``UA_Server_createEvent``. The
+ * `EventId` for the new event is generated automatically and is returned
+ * through ``outEventId``. ``NULL`` can be passed if the `EventId` is not
+ * needed. ``deleteEventNode`` specifies whether the node representation of the
+ * event should be deleted after invoking the method. This can be useful if
+ * events with the similar attributes are triggered frequently. ``UA_TRUE``
+ * would cause the node to be deleted. */
+
+#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
+
+/* Creates a node representation of an event
+ *
+ * @param server The server object
+ * @param eventType The type of the event for which a node should be created
+ * @param outNodeId The NodeId of the newly created node for the event
+ * @return The StatusCode of the UA_Server_createEvent method */
+UA_StatusCode UA_EXPORT UA_THREADSAFE
+UA_Server_createEvent(UA_Server *server, const UA_NodeId eventType,
+ UA_NodeId *outNodeId);
+
+/* Triggers a node representation of an event by applying EventFilters and
+ * adding the event to the appropriate queues.
+ *
+ * @param server The server object
+ * @param eventNodeId The NodeId of the node representation of the event which
+ * should be triggered
+ * @param outEvent the EventId of the new event
+ * @param deleteEventNode Specifies whether the node representation of the event
+ * should be deleted
+ * @return The StatusCode of the UA_Server_triggerEvent method */
+UA_StatusCode UA_EXPORT UA_THREADSAFE
+UA_Server_triggerEvent(UA_Server *server, const UA_NodeId eventNodeId,
+ const UA_NodeId originId, UA_ByteString *outEventId,
+ const UA_Boolean deleteEventNode);
+
+#endif /* UA_ENABLE_SUBSCRIPTIONS_EVENTS */
+
+#ifdef UA_ENABLE_SUBSCRIPTIONS_ALARMS_CONDITIONS
+typedef enum UA_TwoStateVariableCallbackType {
+ UA_ENTERING_ENABLEDSTATE,
+ UA_ENTERING_ACKEDSTATE,
+ UA_ENTERING_CONFIRMEDSTATE,
+ UA_ENTERING_ACTIVESTATE
+} UA_TwoStateVariableCallbackType;
+
+/* Callback prototype to set user specific callbacks */
+typedef UA_StatusCode
+(*UA_TwoStateVariableChangeCallback)(UA_Server *server, const UA_NodeId *condition);
+
+/* Create condition instance. The function checks first whether the passed
+ * conditionType is a subType of ConditionType. Then checks whether the
+ * condition source has HasEventSource reference to its parent. If not, a
+ * HasEventSource reference will be created between condition source and server
+ * object. To expose the condition in address space, a hierarchical
+ * ReferenceType should be passed to create the reference to condition source.
+ * Otherwise, UA_NODEID_NULL should be passed to make the condition not exposed.
+ *
+ * @param server The server object
+ * @param conditionId The NodeId of the requested Condition Object. When passing
+ * UA_NODEID_NUMERIC(X,0) an unused nodeid in namespace X will be used.
+ * E.g. passing UA_NODEID_NULL will result in a NodeId in namespace 0.
+ * @param conditionType The NodeId of the node representation of the ConditionType
+ * @param conditionName The name of the condition to be created
+ * @param conditionSource The NodeId of the Condition Source (Parent of the Condition)
+ * @param hierarchialReferenceType The NodeId of Hierarchical ReferenceType
+ * between Condition and its source
+ * @param outConditionId The NodeId of the created Condition
+ * @return The StatusCode of the UA_Server_createCondition method */
+UA_StatusCode UA_EXPORT
+UA_Server_createCondition(UA_Server *server,
+ const UA_NodeId conditionId,
+ const UA_NodeId conditionType,
+ const UA_QualifiedName conditionName,
+ const UA_NodeId conditionSource,
+ const UA_NodeId hierarchialReferenceType,
+ UA_NodeId *outConditionId);
+
+/* Set the value of condition field.
+ *
+ * @param server The server object
+ * @param condition The NodeId of the node representation of the Condition Instance
+ * @param value Variant Value to be written to the Field
+ * @param fieldName Name of the Field in which the value should be written
+ * @return The StatusCode of the UA_Server_setConditionField method*/
+UA_StatusCode UA_EXPORT
+UA_Server_setConditionField(UA_Server *server,
+ const UA_NodeId condition,
+ const UA_Variant *value,
+ const UA_QualifiedName fieldName);
+
+/* Set the value of property of condition field.
+ *
+ * @param server The server object
+ * @param condition The NodeId of the node representation of the Condition
+ * Instance
+ * @param value Variant Value to be written to the Field
+ * @param variableFieldName Name of the Field which has a property
+ * @param variablePropertyName Name of the Field Property in which the value
+ * should be written
+ * @return The StatusCode of the UA_Server_setConditionVariableFieldProperty*/
+UA_StatusCode UA_EXPORT
+UA_Server_setConditionVariableFieldProperty(UA_Server *server,
+ const UA_NodeId condition,
+ const UA_Variant *value,
+ const UA_QualifiedName variableFieldName,
+ const UA_QualifiedName variablePropertyName);
+
+/* Triggers an event only for an enabled condition. The condition list is
+ * updated then with the last generated EventId.
+ *
+ * @param server The server object
+ * @param condition The NodeId of the node representation of the Condition Instance
+ * @param conditionSource The NodeId of the node representation of the Condition Source
+ * @param outEventId last generated EventId
+ * @return The StatusCode of the UA_Server_triggerConditionEvent method */
+UA_StatusCode UA_EXPORT
+UA_Server_triggerConditionEvent(UA_Server *server,
+ const UA_NodeId condition,
+ const UA_NodeId conditionSource,
+ UA_ByteString *outEventId);
+
+/* Add an optional condition field using its name. (TODO Adding optional methods
+ * is not implemented yet)
+ *
+ * @param server The server object
+ * @param condition The NodeId of the node representation of the Condition Instance
+ * @param conditionType The NodeId of the node representation of the Condition Type
+ * from which the optional field comes
+ * @param fieldName Name of the optional field
+ * @param outOptionalVariable The NodeId of the created field (Variable Node)
+ * @return The StatusCode of the UA_Server_addConditionOptionalField method */
+UA_StatusCode UA_EXPORT
+UA_Server_addConditionOptionalField(UA_Server *server,
+ const UA_NodeId condition,
+ const UA_NodeId conditionType,
+ const UA_QualifiedName fieldName,
+ UA_NodeId *outOptionalVariable);
+
+/* Function used to set a user specific callback to TwoStateVariable Fields of a
+ * condition. The callbacks will be called before triggering the events when
+ * transition to true State of EnabledState/Id, AckedState/Id, ConfirmedState/Id
+ * and ActiveState/Id occurs.
+ *
+ * @param server The server object
+ * @param condition The NodeId of the node representation of the Condition Instance
+ * @param conditionSource The NodeId of the node representation of the Condition Source
+ * @param removeBranch (Not Implemented yet)
+ * @param callback User specific callback function
+ * @param callbackType Callback function type, indicates where it should be called
+ * @return The StatusCode of the UA_Server_setConditionTwoStateVariableCallback method */
+UA_StatusCode UA_EXPORT
+UA_Server_setConditionTwoStateVariableCallback(UA_Server *server,
+ const UA_NodeId condition,
+ const UA_NodeId conditionSource,
+ UA_Boolean removeBranch,
+ UA_TwoStateVariableChangeCallback callback,
+ UA_TwoStateVariableCallbackType callbackType);
+
+/* Delete a condition from the address space and the internal lists.
+ *
+ * @param server The server object
+ * @param condition The NodeId of the node representation of the Condition Instance
+ * @param conditionSource The NodeId of the node representation of the Condition Source
+ * @return ``UA_STATUSCODE_GOOD`` on success */
+UA_StatusCode UA_EXPORT
+UA_Server_deleteCondition(UA_Server *server,
+ const UA_NodeId condition,
+ const UA_NodeId conditionSource);
+
+#endif /* UA_ENABLE_SUBSCRIPTIONS_ALARMS_CONDITIONS */
+
+/**
+ * Update the Server Certificate at Runtime
+ * ---------------------------------------- */
+UA_StatusCode UA_EXPORT
+UA_Server_updateCertificate(UA_Server *server,
+ const UA_ByteString *oldCertificate,
+ const UA_ByteString *newCertificate,
+ const UA_ByteString *newPrivateKey,
+ UA_Boolean closeSessions,
+ UA_Boolean closeSecureChannels);
+
+/**
+ * Utility Functions
+ * ----------------- */
+/* Lookup a datatype by its NodeId. Takes the custom types in the server
+ * configuration into account. Return NULL if none found. */
+UA_EXPORT const UA_DataType *
+UA_Server_findDataType(UA_Server *server, const UA_NodeId *typeId);
+
+/* Add a new namespace to the server. Returns the index of the new namespace */
+UA_UInt16 UA_EXPORT UA_THREADSAFE
+UA_Server_addNamespace(UA_Server *server, const char* name);
+
+/* Get namespace by name from the server. */
+UA_StatusCode UA_EXPORT UA_THREADSAFE
+UA_Server_getNamespaceByName(UA_Server *server, const UA_String namespaceUri,
+ size_t* foundIndex);
+
+/* Get namespace by id from the server. */
+UA_StatusCode UA_EXPORT UA_THREADSAFE
+UA_Server_getNamespaceByIndex(UA_Server *server, const size_t namespaceIndex,
+ UA_String *foundUri);
+
+/**
+* .. _async-operations:
+*
+* Async Operations
+* ----------------
+* Some operations (such as reading out a sensor that needs to warm up) can take
+* quite some time. In order not to block the server during such an operation, it
+* can be "outsourced" to a worker thread.
+*
+* Take the example of a CallRequest. It is split into the individual method call
+* operations. If the method is marked as async, then the operation is put into a
+* queue where it is be retrieved by a worker. The worker returns the result when
+* ready. See the examples in ``/examples/tutorial_server_method_async.c`` for
+* the usage.
+*
+* Note that the operation can time out (see the asyncOperationTimeout setting in
+* the server config) also when it has been retrieved by the worker. */
+
+#if UA_MULTITHREADING >= 100
+
+/* Set the async flag in a method node */
+UA_StatusCode UA_EXPORT
+UA_Server_setMethodNodeAsync(UA_Server *server, const UA_NodeId id,
+ UA_Boolean isAsync);
+
+typedef enum {
+ UA_ASYNCOPERATIONTYPE_INVALID, /* 0, the default */
+ UA_ASYNCOPERATIONTYPE_CALL
+ /* UA_ASYNCOPERATIONTYPE_READ, */
+ /* UA_ASYNCOPERATIONTYPE_WRITE, */
+} UA_AsyncOperationType;
+
+typedef union {
+ UA_CallMethodRequest callMethodRequest;
+ /* UA_ReadValueId readValueId; */
+ /* UA_WriteValue writeValue; */
+} UA_AsyncOperationRequest;
+
+typedef union {
+ UA_CallMethodResult callMethodResult;
+ /* UA_DataValue readResult; */
+ /* UA_StatusCode writeResult; */
+} UA_AsyncOperationResponse;
+
+/* Get the next async operation without blocking
+ *
+ * @param server The server object
+ * @param type The type of the async operation
+ * @param request Receives pointer to the operation
+ * @param context Receives the pointer to the operation context
+ * @param timeout The timestamp when the operation times out and can
+ * no longer be returned to the client. The response has to
+ * be set in UA_Server_setAsyncOperationResult in any case.
+ * @return false if queue is empty, true else */
+UA_Boolean UA_EXPORT
+UA_Server_getAsyncOperationNonBlocking(UA_Server *server, UA_AsyncOperationType *type,
+ const UA_AsyncOperationRequest **request,
+ void **context, UA_DateTime *timeout);
+
+/* UA_Boolean UA_EXPORT */
+/* UA_Server_getAsyncOperationBlocking(UA_Server *server, UA_AsyncOperationType *type, */
+/* const UA_AsyncOperationRequest **request, */
+/* void **context, UA_DateTime *timeout); */
+
+/* Submit an async operation result
+ *
+ * @param server The server object
+ * @param response Pointer to the operation result
+ * @param context Pointer to the operation context */
+void UA_EXPORT
+UA_Server_setAsyncOperationResult(UA_Server *server,
+ const UA_AsyncOperationResponse *response,
+ void *context);
+
+#endif /* !UA_MULTITHREADING >= 100 */
+
+/**
+* Statistics
+* ----------
+*
+* Statistic counters keeping track of the current state of the stack. Counters
+* are structured per OPC UA communication layer. */
+
+typedef struct {
+ UA_NetworkStatistics ns;
+ UA_SecureChannelStatistics scs;
+ UA_SessionStatistics ss;
+} UA_ServerStatistics;
+
+UA_ServerStatistics UA_EXPORT
+UA_Server_getStatistics(UA_Server *server);
_UA_END_DECLS
+#ifdef UA_ENABLE_PUBSUB
+#endif
+
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/include/open62541/client_config.h" ***********************************/
+/**** amalgamated original file "/include/open62541/client.h" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
- * Copyright 2018 (c) Stefan Profanter, fortiss GmbH
+ * Copyright 2015-2020 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
+ * Copyright 2015-2016 (c) Sten Grüner
+ * Copyright 2015-2016 (c) Chris Iatrou
+ * Copyright 2015-2017 (c) Florian Palm
+ * Copyright 2015 (c) Holger Jeromin
+ * Copyright 2015 (c) Oleksiy Vasylyev
+ * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
+ * Copyright 2017 (c) Mark Giraud, Fraunhofer IOSB
* Copyright 2018 (c) Thomas Stalder, Blue Time Concept SA
+ * Copyright 2018 (c) Kalycito Infotech Private Limited
+ * Copyright 2020 (c) Christian von Arnim, ISW University of Stuttgart
*/
-#ifndef UA_CLIENT_CONFIG_H
-#define UA_CLIENT_CONFIG_H
-_UA_BEGIN_DECLS
-struct UA_Client;
-typedef struct UA_Client UA_Client;
+_UA_BEGIN_DECLS
/**
+ * .. _client:
+ *
+ * Client
+ * ======
+ *
+ * The client implementation allows remote access to all OPC UA services. For
+ * convenience, some functionality has been wrapped in :ref:`high-level
+ * abstractions <client-highlevel>`.
+ *
+ * **However**: At this time, the client does not yet contain its own thread or
+ * event-driven main-loop, meaning that the client will not perform any actions
+ * automatically in the background. This is especially relevant for
+ * connection/session management and subscriptions. The user will have to
+ * periodically call `UA_Client_run_iterate` to ensure that asynchronous events
+ * are handled, including keeping a secure connection established.
+ * See more about :ref:`asynchronicity<client-async-services>` and
+ * :ref:`subscriptions<client-subscriptions>`.
+ *
* .. _client-config:
*
* Client Configuration
@@ -27913,17 +29644,23 @@ typedef struct UA_Client UA_Client;
* The :ref:`tutorials` provide a good starting point for this. */
typedef struct {
- /* Basic client configuration */
- void *clientContext; /* User-defined data attached to the client */
- UA_Logger logger; /* Logger used by the client */
- UA_UInt32 timeout; /* Response timeout in ms */
+ void *clientContext; /* User-defined pointer attached to the client */
+ UA_Logger logger; /* Logger used by the client */
+ UA_UInt32 timeout; /* Response timeout in ms */
/* The description must be internally consistent.
* - The ApplicationUri set in the ApplicationDescription must match the
- * URI set in the server certificate */
+ * URI set in the certificate */
UA_ApplicationDescription clientDescription;
- /* Basic connection configuration */
+ /**
+ * Connection configuration
+ * ~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * The following configuration elements reduce the "degrees of freedom" the
+ * client has when connecting to a server. If no connection can be made
+ * under these restrictions, then the connection will abort with an error
+ * message. */
UA_ExtensionObject userIdentityToken; /* Configured User-Identity Token */
UA_MessageSecurityMode securityMode; /* None, Sign, SignAndEncrypt. The
* default is invalid. This indicates
@@ -27933,8 +29670,7 @@ typedef struct {
* empty string indicates the client to select
* any matching SecurityPolicy. */
- /* Advanced connection configuration
- *
+ /**
* If either endpoint or userTokenPolicy has been set (at least one non-zero
* byte in either structure), then the selected Endpoint and UserTokenPolicy
* overwrite the settings in the basic connection configuration. The
@@ -27949,7 +29685,22 @@ typedef struct {
UA_EndpointDescription endpoint;
UA_UserTokenPolicy userTokenPolicy;
- /* Advanced client configuration */
+ /**
+ * Custom Data Types
+ * ~~~~~~~~~~~~~~~~~
+ * The following is a linked list of arrays with custom data types. All data
+ * types that are accessible from here are automatically considered for the
+ * decoding of received messages. Custom data types are not cleaned up
+ * together with the configuration. So it is possible to allocate them on
+ * ROM.
+ *
+ * See the section on :ref:`generic-types`. Examples for working with custom
+ * data types are provided in ``/examples/custom_datatype/``. */
+ const UA_DataTypeArray *customDataTypes;
+
+ /**
+ * Advanced Client Configuration
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
UA_UInt32 secureChannelLifeTime; /* Lifetime in ms (then the channel needs
to be renewed) */
@@ -27957,12 +29708,6 @@ typedef struct {
UA_ConnectionConfig localConnectionConfig;
UA_UInt32 connectivityCheckInterval; /* Connectivity check interval in ms.
* 0 = background task disabled */
- const UA_DataTypeArray *customDataTypes; /* Custom DataTypes. Attention!
- * Custom datatypes are not cleaned
- * up together with the
- * configuration. So it is possible
- * to allocate them on ROM. */
-
/* Available SecurityPolicies */
size_t securityPoliciesSize;
UA_SecurityPolicy *securityPolicies;
@@ -27972,8 +29717,9 @@ typedef struct {
/* Callbacks for async connection handshakes */
UA_ConnectClientConnection initConnectionFunc;
- UA_StatusCode (*pollConnectionFunc)(UA_Client *client, void *context,
- UA_UInt32 timeout);
+ UA_StatusCode (*pollConnectionFunc)(UA_Connection *connection,
+ UA_UInt32 timeout,
+ const UA_Logger *logger);
/* Callback for state changes. The client state is differentated into the
* SecureChannel state and the Session state. The connectStatus is set if
@@ -27986,7 +29732,7 @@ typedef struct {
UA_StatusCode connectStatus);
/* When connectivityCheckInterval is greater than 0, every
- * connectivityCheckInterval (in ms), a async read request is performed on
+ * connectivityCheckInterval (in ms), an async read request is performed on
* the server. inactivityCallback is called when the client receive no
* response for this read request The connection can be closed, this in an
* attempt to recreate a healthy connection. */
@@ -28004,54 +29750,12 @@ typedef struct {
UA_UInt32 subscriptionId,
void *subContext);
#endif
-} UA_ClientConfig;
-
-_UA_END_DECLS
-
-#endif /* UA_CLIENT_CONFIG_H */
-
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/include/open62541/client.h" ***********************************/
-
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- *
- * Copyright 2015-2020 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
- * Copyright 2015-2016 (c) Sten Grüner
- * Copyright 2015-2016 (c) Chris Iatrou
- * Copyright 2015-2017 (c) Florian Palm
- * Copyright 2015 (c) Holger Jeromin
- * Copyright 2015 (c) Oleksiy Vasylyev
- * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
- * Copyright 2017 (c) Mark Giraud, Fraunhofer IOSB
- * Copyright 2018 (c) Thomas Stalder, Blue Time Concept SA
- * Copyright 2018 (c) Kalycito Infotech Private Limited
- */
-
-
-_UA_BEGIN_DECLS
+ UA_LocaleId *sessionLocaleIds;
+ size_t sessionLocaleIdsSize;
+} UA_ClientConfig;
-/**
- * .. _client:
- *
- * Client
- * ======
- *
- * The client implementation allows remote access to all OPC UA services. For
- * convenience, some functionality has been wrapped in :ref:`high-level
- * abstractions <client-highlevel>`.
- *
- * **However**: At this time, the client does not yet contain its own thread or
- * event-driven main-loop. So the client will not perform any actions
- * automatically in the background. This is especially relevant for
- * subscriptions. The user will have to periodically call
- * `UA_Client_Subscriptions_manuallySendPublishRequest`. See also :ref:`here
- * <client-subscriptions>`.
- *
- *
- * .. include:: client_config.rst
- *
+ /**
* Client Lifecycle
* ---------------- */
@@ -28165,35 +29869,6 @@ UA_Client_disconnectAsync(UA_Client *client);
UA_StatusCode UA_EXPORT
UA_Client_disconnectSecureChannel(UA_Client *client);
-/* Deprecated methods */
-
-UA_DEPRECATED static UA_INLINE UA_StatusCode
-UA_Client_connect_async(UA_Client *client, const char *endpointUrl) {
- return UA_Client_connectAsync(client, endpointUrl);
-}
-
-UA_DEPRECATED static UA_INLINE UA_StatusCode
-UA_Client_connect_noSession(UA_Client *client, const char *endpointUrl) {
- return UA_Client_connectSecureChannel(client, endpointUrl);
-}
-
-UA_DEPRECATED static UA_INLINE UA_StatusCode
-UA_Client_connect_username(UA_Client *client, const char *endpointUrl,
- const char *username, const char *password) {
- return UA_Client_connectUsername(client, endpointUrl,
- username, password);
-}
-
-UA_DEPRECATED static UA_INLINE UA_StatusCode
-UA_Client_disconnect_async(UA_Client *client, UA_UInt32 *requestId) {
- return UA_Client_disconnect(client);
-}
-
-UA_DEPRECATED static UA_INLINE UA_StatusCode
-UA_Client_close(UA_Client *client) {
- return UA_Client_disconnect(client);
-}
-
/**
* Discovery
* --------- */
@@ -28452,8 +30127,22 @@ UA_Client_Service_queryNext(UA_Client *client,
* Asynchronous Services
* ---------------------
* All OPC UA services are asynchronous in nature. So several service calls can
- * be made without waiting for a response first. Responess may come in a
- * different ordering. */
+ * be made without waiting for the individual responses. Depending on the
+ * server's priorities responses may come in a different ordering than sent.
+ *
+ * As noted in :ref:`the client overview<client>` currently no means
+ * of handling asynchronous events automatically is provided. However, some
+ * synchronous function calls will trigger handling, but to ensure this
+ * happens a client should periodically call `UA_Client_run_iterate`
+ * explicitly.
+ *
+ * Connection and session management are also performed in
+ * `UA_Client_run_iterate`, so to keep a connection healthy any client need to
+ * consider how and when it is appropriate to do the call.
+ * This is especially true for the periodic renewal of a SecureChannel's
+ * SecurityToken which is designed to have a limited lifetime and will
+ * invalidate the connection if not renewed.
+ */
/* Use the type versions of this method. See below. However, the general
* mechanism of async service calls is explained here.
@@ -28477,7 +30166,7 @@ UA_Client_Service_queryNext(UA_Client *client,
* The userdata and requestId arguments can be NULL. */
typedef void (*UA_ClientAsyncServiceCallback)(UA_Client *client, void *userdata,
- UA_UInt32 requestId, void *response);
+ UA_UInt32 requestId, void *response);
UA_StatusCode UA_EXPORT
__UA_Client_AsyncService(UA_Client *client, const void *request,
@@ -28491,21 +30180,36 @@ UA_Client_sendAsyncRequest(UA_Client *client, const void *request,
const UA_DataType *requestType, UA_ClientAsyncServiceCallback callback,
const UA_DataType *responseType, void *userdata, UA_UInt32 *requestId);
+/* Set new userdata and callback for an existing request.
+ *
+ * @param client Pointer to the UA_Client
+ * @param requestId RequestId of the request, which was returned by
+ * UA_Client_sendAsyncRequest before
+ * @param userdata The new userdata.
+ * @param callback The new callback
+ * @return UA_StatusCode UA_STATUSCODE_GOOD on success
+ * UA_STATUSCODE_BADNOTFOUND when no request with requestId is found. */
+UA_StatusCode UA_EXPORT
+UA_Client_modifyAsyncCallback(UA_Client *client, UA_UInt32 requestId,
+ void *userdata, UA_ClientAsyncServiceCallback callback);
+
/* Listen on the network and process arriving asynchronous responses in the
* background. Internal housekeeping, renewal of SecureChannels and subscription
* management is done as well. */
UA_StatusCode UA_EXPORT
UA_Client_run_iterate(UA_Client *client, UA_UInt32 timeout);
-UA_DEPRECATED static UA_INLINE UA_StatusCode
-UA_Client_runAsync(UA_Client *client, UA_UInt32 timeout) {
- return UA_Client_run_iterate(client, timeout);
-}
-
-UA_DEPRECATED static UA_INLINE UA_StatusCode
-UA_Client_manuallyRenewSecureChannel(UA_Client *client) {
- return UA_Client_run_iterate(client, 0);
-}
+/* Force the manual renewal of the SecureChannel. This is useful to renew the
+ * SecureChannel during a downtime when no time-critical operations are
+ * performed. This method is asynchronous. The renewal is triggered (the OPN
+ * message is sent) but not completed. The OPN response is handled with
+ * ``UA_Client_run_iterate`` or a synchronous servica-call operation.
+ *
+ * @return The return value is UA_STATUSCODE_GOODCALLAGAIN if the SecureChannel
+ * has not elapsed at least 75% of its lifetime. Otherwise the
+ * ``connectStatus`` is returned. */
+UA_StatusCode UA_EXPORT
+UA_Client_renewSecureChannel(UA_Client *client);
/* Use the type versions of this method. See below. However, the general
* mechanism of async service calls is explained here.
@@ -28585,10 +30289,14 @@ UA_Client_changeRepeatedCallbackInterval(UA_Client *client,
void UA_EXPORT
UA_Client_removeCallback(UA_Client *client, UA_UInt64 callbackId);
-UA_DEPRECATED static UA_INLINE void
-UA_Client_removeRepeatedCallback(UA_Client *client, UA_UInt64 callbackId) {
- UA_Client_removeCallback(client, callbackId);
-}
+/**
+ * Client Utility Functions
+ * ------------------------ */
+
+/* Lookup a datatype by its NodeId. Takes the custom types in the client
+ * configuration into account. Return NULL if none found. */
+UA_EXPORT const UA_DataType *
+UA_Client_findDataType(UA_Client *client, const UA_NodeId *typeId);
/**
* .. toctree::
@@ -28599,7 +30307,7 @@ UA_Client_removeRepeatedCallback(UA_Client *client, UA_UInt64 callbackId) {
_UA_END_DECLS
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/include/open62541/client_highlevel.h" ***********************************/
+/**** amalgamated original file "/include/open62541/client_highlevel.h" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -29258,7 +30966,7 @@ UA_Client_forEachChildNodeCall(UA_Client *client, UA_NodeId parentNodeId,
_UA_END_DECLS
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/include/open62541/client_subscriptions.h" ***********************************/
+/**** amalgamated original file "/include/open62541/client_subscriptions.h" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -29289,7 +30997,9 @@ _UA_BEGIN_DECLS
* The client automatically processes PublishResponses (with a callback) in the
* background and keeps enough PublishRequests in transit. The PublishResponses
* may be recieved during a synchronous service call or in
- * ``UA_Client_runAsync``. */
+ * ``UA_Client_run_iterate``. See more about
+ * :ref:`asynchronicity<client-async-services>`.
+ */
/* Callbacks defined for Subscriptions */
typedef void (*UA_Client_DeleteSubscriptionCallback)
@@ -29398,7 +31108,7 @@ UA_MonitoredItemCreateRequest_default(UA_NodeId nodeId) {
}
/**
- * The clientHandle parameter can't be set by the user, any value will be replaced
+ * The clientHandle parameter cannot be set by the user, any value will be replaced
* by the client before sending the request to the server. */
/* Callback for the deletion of a MonitoredItem */
@@ -29546,7 +31256,7 @@ UA_Client_MonitoredItems_setTriggering_async(UA_Client *client,
_UA_END_DECLS
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/include/open62541/client_highlevel_async.h" ***********************************/
+/**** amalgamated original file "/include/open62541/client_highlevel_async.h" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -29561,8 +31271,11 @@ _UA_END_DECLS
_UA_BEGIN_DECLS
/**
- * Raw Services
- * ^^^^^^^^^^^^ */
+ * Async Services
+ * ^^^^^^^^^^^^^^
+ *
+ * Call OPC UA Services asynchronously with a callback. The (optional) requestId
+ * output can be used to cancel the service while it is still pending. */
typedef void (*UA_ClientAsyncReadCallback)(UA_Client *client, void *userdata,
UA_UInt32 requestId, UA_ReadResponse *rr);
@@ -29599,287 +31312,256 @@ UA_Client_sendAsyncBrowseRequest(UA_Client *client, UA_BrowseRequest *request,
}
/**
+ * Asynchronous Operations
+ * ^^^^^^^^^^^^^^^^^^^^^^^
+ *
+ * Many Services can be called with an array of operations. For example, a
+ * request to the Read Service contains an array of ReadValueId, each
+ * corresponding to a single read operation. For convenience, wrappers are
+ * provided to call single operations for the most common Services.
+ *
+ * All async operations have a callback of the following structure: The returned
+ * StatusCode is split in two parts. The status indicates the overall success of
+ * the request and the operation. The result argument is non-NULL only if the
+ * status is no good. */
+typedef void
+(*UA_ClientAsyncOperationCallback)(UA_Client *client, void *userdata,
+ UA_UInt32 requestId, UA_StatusCode status,
+ void *result);
+
+/**
* Read Attribute
- * ^^^^^^^^^^^^^^ */
+ * ^^^^^^^^^^^^^^
+ *
+ * Asynchronously read a single attribute. The attribute is unpacked from the
+ * response as the datatype of the attribute is known ahead of time. Value
+ * attributes are variants.
+ *
+ * Note that the last argument (value pointer) of the callbacks can be NULL if
+ * the status of the operation is not good. */
+
+/* Reading a single attribute */
+typedef void
+(*UA_ClientAsyncReadAttributeCallback)(UA_Client *client, void *userdata,
+ UA_UInt32 requestId, UA_StatusCode status,
+ UA_DataValue *attribute);
UA_StatusCode UA_EXPORT
-__UA_Client_readAttribute_async(UA_Client *client, const UA_NodeId *nodeId,
- UA_AttributeId attributeId,
- const UA_DataType *outDataType,
- UA_ClientAsyncServiceCallback callback, void *userdata,
- UA_UInt32 *reqId);
-
-typedef void (*UA_ClientAsyncReadDataTypeAttributeCallback)(UA_Client *client,
- void *userdata,
- UA_UInt32 requestId,
- UA_NodeId *var);
-static UA_INLINE UA_StatusCode
-UA_Client_readDataTypeAttribute_async(
- UA_Client *client, const UA_NodeId nodeId,
- UA_ClientAsyncReadDataTypeAttributeCallback callback, void *userdata,
- UA_UInt32 *reqId) {
- return __UA_Client_readAttribute_async(
- client, &nodeId, UA_ATTRIBUTEID_DATATYPE, &UA_TYPES[UA_TYPES_NODEID],
- (UA_ClientAsyncServiceCallback)callback, userdata, reqId);
-}
+UA_Client_readAttribute_async(UA_Client *client, const UA_ReadValueId *rvi,
+ UA_TimestampsToReturn timestampsToReturn,
+ UA_ClientAsyncReadAttributeCallback callback,
+ void *userdata, UA_UInt32 *requestId);
-typedef void (*UA_ClientAsyncReadValueAttributeCallback)(UA_Client *client,
- void *userdata,
- UA_UInt32 requestId,
- UA_Variant *var);
-static UA_INLINE UA_StatusCode
+/* Read a single Value attribute */
+typedef void
+(*UA_ClientAsyncReadValueAttributeCallback)(UA_Client *client, void *userdata,
+ UA_UInt32 requestId, UA_StatusCode status,
+ UA_DataValue *value);
+UA_StatusCode UA_EXPORT
UA_Client_readValueAttribute_async(UA_Client *client, const UA_NodeId nodeId,
UA_ClientAsyncReadValueAttributeCallback callback,
- void *userdata, UA_UInt32 *reqId) {
- return __UA_Client_readAttribute_async(
- client, &nodeId, UA_ATTRIBUTEID_VALUE, &UA_TYPES[UA_TYPES_VARIANT],
- (UA_ClientAsyncServiceCallback)callback, userdata, reqId);
-}
+ void *userdata, UA_UInt32 *requestId);
+
+/* Read a single DataType attribute */
+typedef void
+(*UA_ClientAsyncReadDataTypeAttributeCallback)(UA_Client *client, void *userdata,
+ UA_UInt32 requestId, UA_StatusCode status,
+ UA_NodeId *dataType);
+UA_StatusCode UA_EXPORT
+UA_Client_readDataTypeAttribute_async(UA_Client *client, const UA_NodeId nodeId,
+ UA_ClientAsyncReadDataTypeAttributeCallback callback,
+ void *userdata, UA_UInt32 *requestId);
+
+/* Read a single ArrayDimensions attribute. If the status is good, the variant
+ * carries an UInt32 array. */
+typedef void
+(*UA_ClientReadArrayDimensionsAttributeCallback)(UA_Client *client, void *userdata,
+ UA_UInt32 requestId, UA_StatusCode status,
+ UA_Variant *arrayDimensions);
+UA_StatusCode UA_EXPORT
+UA_Client_readArrayDimensionsAttribute_async(UA_Client *client, const UA_NodeId nodeId,
+ UA_ClientReadArrayDimensionsAttributeCallback callback,
+ void *userdata, UA_UInt32 *requestId);
+
+/* Read a single NodeClass attribute */
+typedef void
+(*UA_ClientAsyncReadNodeClassAttributeCallback)(UA_Client *client, void *userdata,
+ UA_UInt32 requestId, UA_StatusCode status,
+ UA_NodeClass *nodeClass);
+UA_StatusCode UA_EXPORT
+UA_Client_readNodeClassAttribute_async(UA_Client *client, const UA_NodeId nodeId,
+ UA_ClientAsyncReadNodeClassAttributeCallback callback,
+ void *userdata, UA_UInt32 *requestId);
+
+/* Read a single BrowseName attribute */
+typedef void
+(*UA_ClientAsyncReadBrowseNameAttributeCallback)(UA_Client *client, void *userdata,
+ UA_UInt32 requestId, UA_StatusCode status,
+ UA_QualifiedName *browseName);
+UA_StatusCode UA_EXPORT
+UA_Client_readBrowseNameAttribute_async(UA_Client *client, const UA_NodeId nodeId,
+ UA_ClientAsyncReadBrowseNameAttributeCallback callback,
+ void *userdata, UA_UInt32 *requestId);
+
+/* Read a single DisplayName attribute */
+typedef void
+(*UA_ClientAsyncReadDisplayNameAttributeCallback)(UA_Client *client, void *userdata,
+ UA_UInt32 requestId, UA_StatusCode status,
+ UA_LocalizedText *displayName);
+UA_StatusCode UA_EXPORT
+UA_Client_readDisplayNameAttribute_async(UA_Client *client, const UA_NodeId nodeId,
+ UA_ClientAsyncReadDisplayNameAttributeCallback callback,
+ void *userdata, UA_UInt32 *requestId);
+
+/* Read a single Description attribute */
+typedef void
+(*UA_ClientAsyncReadDescriptionAttributeCallback)(UA_Client *client, void *userdata,
+ UA_UInt32 requestId, UA_StatusCode status,
+ UA_LocalizedText *description);
+UA_StatusCode UA_EXPORT
+UA_Client_readDescriptionAttribute_async(UA_Client *client, const UA_NodeId nodeId,
+ UA_ClientAsyncReadDescriptionAttributeCallback callback,
+ void *userdata, UA_UInt32 *requestId);
+
+/* Read a single WriteMask attribute */
+typedef void
+(*UA_ClientAsyncReadWriteMaskAttributeCallback)(UA_Client *client, void *userdata,
+ UA_UInt32 requestId, UA_StatusCode status,
+ UA_UInt32 *writeMask);
+UA_StatusCode UA_EXPORT
+UA_Client_readWriteMaskAttribute_async(UA_Client *client, const UA_NodeId nodeId,
+ UA_ClientAsyncReadWriteMaskAttributeCallback callback,
+ void *userdata, UA_UInt32 *requestId);
+
+/* Read a single UserWriteMask attribute */
+typedef void
+(*UA_ClientAsyncReadUserWriteMaskAttributeCallback)(UA_Client *client, void *userdata,
+ UA_UInt32 requestId, UA_StatusCode status,
+ UA_UInt32 *writeMask);
+UA_StatusCode UA_EXPORT
+UA_Client_readUserWriteMaskAttribute_async(UA_Client *client, const UA_NodeId nodeId,
+ UA_ClientAsyncReadUserWriteMaskAttributeCallback callback,
+ void *userdata, UA_UInt32 *requestId);
+
+/* Read a single IsAbstract attribute */
+typedef void
+(*UA_ClientAsyncReadIsAbstractAttributeCallback)(UA_Client *client, void *userdata,
+ UA_UInt32 requestId, UA_StatusCode status,
+ UA_Boolean *isAbstract);
+UA_StatusCode UA_EXPORT
+UA_Client_readIsAbstractAttribute_async(UA_Client *client, const UA_NodeId nodeId,
+ UA_ClientAsyncReadIsAbstractAttributeCallback callback,
+ void *userdata, UA_UInt32 *requestId);
+
+/* Read a single Symmetric attribute */
+typedef void
+(*UA_ClientAsyncReadSymmetricAttributeCallback)(UA_Client *client, void *userdata,
+ UA_UInt32 requestId, UA_StatusCode status,
+ UA_Boolean *symmetric);
+UA_StatusCode UA_EXPORT
+UA_Client_readSymmetricAttribute_async(UA_Client *client, const UA_NodeId nodeId,
+ UA_ClientAsyncReadSymmetricAttributeCallback callback,
+ void *userdata, UA_UInt32 *requestId);
+
+/* Read a single InverseName attribute */
+typedef void
+(*UA_ClientAsyncReadInverseNameAttributeCallback)(UA_Client *client, void *userdata,
+ UA_UInt32 requestId, UA_StatusCode status,
+ UA_LocalizedText *inverseName);
+UA_StatusCode UA_EXPORT
+UA_Client_readInverseNameAttribute_async(UA_Client *client, const UA_NodeId nodeId,
+ UA_ClientAsyncReadInverseNameAttributeCallback callback,
+ void *userdata, UA_UInt32 *requestId);
+
+/* Read a single ContainsNoLoops attribute */
+typedef void
+(*UA_ClientAsyncReadContainsNoLoopsAttributeCallback)(UA_Client *client, void *userdata,
+ UA_UInt32 requestId, UA_StatusCode status,
+ UA_Boolean *containsNoLoops);
+UA_StatusCode UA_EXPORT
+UA_Client_readContainsNoLoopsAttribute_async(UA_Client *client, const UA_NodeId nodeId,
+ UA_ClientAsyncReadContainsNoLoopsAttributeCallback callback,
+ void *userdata, UA_UInt32 *requestId);
+
+/* Read a single EventNotifier attribute */
+typedef void
+(*UA_ClientAsyncReadEventNotifierAttributeCallback)(UA_Client *client, void *userdata,
+ UA_UInt32 requestId, UA_StatusCode status,
+ UA_Byte *eventNotifier);
+UA_StatusCode UA_EXPORT
+UA_Client_readEventNotifierAttribute_async(UA_Client *client, const UA_NodeId nodeId,
+ UA_ClientAsyncReadEventNotifierAttributeCallback callback,
+ void *userdata, UA_UInt32 *requestId);
+
+/* Read a single ValueRank attribute */
+typedef void
+(*UA_ClientAsyncReadValueRankAttributeCallback)(UA_Client *client, void *userdata,
+ UA_UInt32 requestId, UA_StatusCode status,
+ UA_Int32 *valueRank);
+UA_StatusCode UA_EXPORT
+UA_Client_readValueRankAttribute_async(UA_Client *client, const UA_NodeId nodeId,
+ UA_ClientAsyncReadValueRankAttributeCallback callback,
+ void *userdata, UA_UInt32 *requestId);
+
+/* Read a single AccessLevel attribute */
+typedef void
+(*UA_ClientAsyncReadAccessLevelAttributeCallback)(UA_Client *client, void *userdata,
+ UA_UInt32 requestId, UA_StatusCode status,
+ UA_Byte *accessLevel);
+UA_StatusCode UA_EXPORT
+UA_Client_readAccessLevelAttribute_async(UA_Client *client, const UA_NodeId nodeId,
+ UA_ClientAsyncReadAccessLevelAttributeCallback callback,
+ void *userdata, UA_UInt32 *requestId);
+
+/* Read a single UserAccessLevel attribute */
+typedef void
+(*UA_ClientAsyncReadUserAccessLevelAttributeCallback)(UA_Client *client, void *userdata,
+ UA_UInt32 requestId, UA_StatusCode status,
+ UA_Byte *userAccessLevel);
+UA_StatusCode UA_EXPORT
+UA_Client_readUserAccessLevelAttribute_async(UA_Client *client, const UA_NodeId nodeId,
+ UA_ClientAsyncReadUserAccessLevelAttributeCallback callback,
+ void *userdata, UA_UInt32 *requestId);
+
+/* Read a single MinimumSamplingInterval attribute */
+typedef void
+(*UA_ClientAsyncReadMinimumSamplingIntervalAttributeCallback)(UA_Client *client, void *userdata,
+ UA_UInt32 requestId, UA_StatusCode status,
+ UA_Double *minimumSamplingInterval);
+UA_StatusCode UA_EXPORT
+UA_Client_readMinimumSamplingIntervalAttribute_async(UA_Client *client, const UA_NodeId nodeId,
+ UA_ClientAsyncReadMinimumSamplingIntervalAttributeCallback callback,
+ void *userdata, UA_UInt32 *requestId);
+
+/* Read a single Historizing attribute */
+typedef void
+(*UA_ClientAsyncReadHistorizingAttributeCallback)(UA_Client *client, void *userdata,
+ UA_UInt32 requestId, UA_StatusCode status,
+ UA_Boolean *historizing);
+UA_StatusCode UA_EXPORT
+UA_Client_readHistorizingAttribute_async(UA_Client *client, const UA_NodeId nodeId,
+ UA_ClientAsyncReadHistorizingAttributeCallback callback,
+ void *userdata, UA_UInt32 *requestId);
+
+/* Read a single Executable attribute */
+typedef void
+(*UA_ClientAsyncReadExecutableAttributeCallback)(UA_Client *client, void *userdata,
+ UA_UInt32 requestId, UA_StatusCode status,
+ UA_Boolean *executable);
+UA_StatusCode UA_EXPORT
+UA_Client_readExecutableAttribute_async(UA_Client *client, const UA_NodeId nodeId,
+ UA_ClientAsyncReadExecutableAttributeCallback callback,
+ void *userdata, UA_UInt32 *requestId);
+
+/* Read a single UserExecutable attribute */
+typedef void
+(*UA_ClientAsyncReadUserExecutableAttributeCallback)(UA_Client *client, void *userdata,
+ UA_UInt32 requestId, UA_StatusCode status,
+ UA_Boolean *userExecutable);
+UA_StatusCode UA_EXPORT
+UA_Client_readUserExecutableAttribute_async(UA_Client *client, const UA_NodeId nodeId,
+ UA_ClientAsyncReadUserExecutableAttributeCallback callback,
+ void *userdata, UA_UInt32 *requestId);
-typedef void (*UA_ClientAsyncReadNodeIdAttributeCallback)(UA_Client *client,
- void *userdata,
- UA_UInt32 requestId,
- UA_NodeId *out);
-static UA_INLINE UA_StatusCode
-UA_Client_readNodeIdAttribute_async(UA_Client *client, const UA_NodeId nodeId,
- UA_ClientAsyncReadNodeIdAttributeCallback callback,
- void *userdata, UA_UInt32 *reqId) {
- return __UA_Client_readAttribute_async(
- client, &nodeId, UA_ATTRIBUTEID_NODEID, &UA_TYPES[UA_TYPES_NODEID],
- (UA_ClientAsyncServiceCallback)callback, userdata, reqId);
-}
-typedef void (*UA_ClientAsyncReadNodeClassAttributeCallback)(UA_Client *client,
- void *userdata,
- UA_UInt32 requestId,
- UA_NodeClass *out);
-static UA_INLINE UA_StatusCode
-UA_Client_readNodeClassAttribute_async(
- UA_Client *client, const UA_NodeId nodeId,
- UA_ClientAsyncReadNodeClassAttributeCallback callback, void *userdata,
- UA_UInt32 *reqId) {
- return __UA_Client_readAttribute_async(
- client, &nodeId, UA_ATTRIBUTEID_NODECLASS, &UA_TYPES[UA_TYPES_NODECLASS],
- (UA_ClientAsyncServiceCallback)callback, userdata, reqId);
-}
-typedef void (*UA_ClientAsyncReadBrowseNameAttributeCallback)(UA_Client *client,
- void *userdata,
- UA_UInt32 requestId,
- UA_QualifiedName *out);
-static UA_INLINE UA_StatusCode
-UA_Client_readBrowseNameAttribute_async(
- UA_Client *client, const UA_NodeId nodeId,
- UA_ClientAsyncReadBrowseNameAttributeCallback callback, void *userdata,
- UA_UInt32 *reqId) {
- return __UA_Client_readAttribute_async(
- client, &nodeId, UA_ATTRIBUTEID_BROWSENAME, &UA_TYPES[UA_TYPES_QUALIFIEDNAME],
- (UA_ClientAsyncServiceCallback)callback, userdata, reqId);
-}
-typedef void (*UA_ClientAsyncReadDisplayNameAttributeCallback)(UA_Client *client,
- void *userdata,
- UA_UInt32 requestId,
- UA_LocalizedText *out);
-static UA_INLINE UA_StatusCode
-UA_Client_readDisplayNameAttribute_async(
- UA_Client *client, const UA_NodeId nodeId,
- UA_ClientAsyncReadDisplayNameAttributeCallback callback, void *userdata,
- UA_UInt32 *reqId) {
- return __UA_Client_readAttribute_async(
- client, &nodeId, UA_ATTRIBUTEID_DISPLAYNAME, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT],
- (UA_ClientAsyncServiceCallback)callback, userdata, reqId);
-}
-typedef void (*UA_ClientAsyncReadDescriptionAttributeCallback)(UA_Client *client,
- void *userdata,
- UA_UInt32 requestId,
- UA_LocalizedText *out);
-static UA_INLINE UA_StatusCode
-UA_Client_readDescriptionAttribute_async(
- UA_Client *client, const UA_NodeId nodeId,
- UA_ClientAsyncReadDescriptionAttributeCallback callback, void *userdata,
- UA_UInt32 *reqId) {
- return __UA_Client_readAttribute_async(
- client, &nodeId, UA_ATTRIBUTEID_DESCRIPTION, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT],
- (UA_ClientAsyncServiceCallback)callback, userdata, reqId);
-}
-typedef void (*UA_ClientAsyncReadWriteMaskAttributeCallback)(UA_Client *client,
- void *userdata,
- UA_UInt32 requestId,
- UA_UInt32 *out);
-static UA_INLINE UA_StatusCode
-UA_Client_readWriteMaskAttribute_async(
- UA_Client *client, const UA_NodeId nodeId,
- UA_ClientAsyncReadWriteMaskAttributeCallback callback, void *userdata,
- UA_UInt32 *reqId) {
- return __UA_Client_readAttribute_async(
- client, &nodeId, UA_ATTRIBUTEID_WRITEMASK, &UA_TYPES[UA_TYPES_UINT32],
- (UA_ClientAsyncServiceCallback)callback, userdata, reqId);
-}
-typedef void (*UA_ClientAsyncReadUserWriteMaskAttributeCallback)(UA_Client *client,
- void *userdata,
- UA_UInt32 requestId,
- UA_UInt32 *out);
-static UA_INLINE UA_StatusCode
-UA_Client_readUserWriteMaskAttribute_async(
- UA_Client *client, const UA_NodeId nodeId,
- UA_ClientAsyncReadUserWriteMaskAttributeCallback callback, void *userdata,
- UA_UInt32 *reqId) {
- return __UA_Client_readAttribute_async(
- client, &nodeId, UA_ATTRIBUTEID_USERWRITEMASK, &UA_TYPES[UA_TYPES_UINT32],
- (UA_ClientAsyncServiceCallback)callback, userdata, reqId);
-}
-typedef void (*UA_ClientAsyncReadIsAbstractAttributeCallback)(UA_Client *client,
- void *userdata,
- UA_UInt32 requestId,
- UA_Boolean *out);
-static UA_INLINE UA_StatusCode
-UA_Client_readIsAbstractAttribute_async(
- UA_Client *client, const UA_NodeId nodeId,
- UA_ClientAsyncReadIsAbstractAttributeCallback callback, void *userdata,
- UA_UInt32 *reqId) {
- return __UA_Client_readAttribute_async(
- client, &nodeId, UA_ATTRIBUTEID_ISABSTRACT, &UA_TYPES[UA_TYPES_BOOLEAN],
- (UA_ClientAsyncServiceCallback)callback, userdata, reqId);
-}
-typedef void (*UA_ClientAsyncReadSymmetricAttributeCallback)(UA_Client *client,
- void *userdata,
- UA_UInt32 requestId,
- UA_Boolean *out);
-static UA_INLINE UA_StatusCode
-UA_Client_readSymmetricAttribute_async(
- UA_Client *client, const UA_NodeId nodeId,
- UA_ClientAsyncReadSymmetricAttributeCallback callback, void *userdata,
- UA_UInt32 *reqId) {
- return __UA_Client_readAttribute_async(
- client, &nodeId, UA_ATTRIBUTEID_SYMMETRIC, &UA_TYPES[UA_TYPES_BOOLEAN],
- (UA_ClientAsyncServiceCallback)callback, userdata, reqId);
-}
-typedef void (*UA_ClientAsyncReadInverseNameAttributeCallback)(UA_Client *client,
- void *userdata,
- UA_UInt32 requestId,
- UA_LocalizedText *out);
-static UA_INLINE UA_StatusCode
-UA_Client_readInverseNameAttribute_async(
- UA_Client *client, const UA_NodeId nodeId,
- UA_ClientAsyncReadInverseNameAttributeCallback callback, void *userdata,
- UA_UInt32 *reqId) {
- return __UA_Client_readAttribute_async(
- client, &nodeId, UA_ATTRIBUTEID_INVERSENAME, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT],
- (UA_ClientAsyncServiceCallback)callback, userdata, reqId);
-}
-typedef void (*UA_ClientAsyncReadContainsNoLoopsAttributeCallback)(UA_Client *client,
- void *userdata,
- UA_UInt32 requestId,
- UA_Boolean *out);
-static UA_INLINE UA_StatusCode
-UA_Client_readContainsNoLoopsAttribute_async(
- UA_Client *client, const UA_NodeId nodeId,
- UA_ClientAsyncReadContainsNoLoopsAttributeCallback callback, void *userdata,
- UA_UInt32 *reqId) {
- return __UA_Client_readAttribute_async(
- client, &nodeId, UA_ATTRIBUTEID_CONTAINSNOLOOPS, &UA_TYPES[UA_TYPES_BOOLEAN],
- (UA_ClientAsyncServiceCallback)callback, userdata, reqId);
-}
-typedef void (*UA_ClientAsyncReadEventNotifierAttributeCallback)(UA_Client *client,
- void *userdata,
- UA_UInt32 requestId,
- UA_Byte *out);
-static UA_INLINE UA_StatusCode
-UA_Client_readEventNotifierAttribute_async(
- UA_Client *client, const UA_NodeId nodeId,
- UA_ClientAsyncReadEventNotifierAttributeCallback callback, void *userdata,
- UA_UInt32 *reqId) {
- return __UA_Client_readAttribute_async(
- client, &nodeId, UA_ATTRIBUTEID_EVENTNOTIFIER, &UA_TYPES[UA_TYPES_BYTE],
- (UA_ClientAsyncServiceCallback)callback, userdata, reqId);
-}
-typedef void (*UA_ClientAsyncReadValueRankAttributeCallback)(UA_Client *client,
- void *userdata,
- UA_UInt32 requestId,
- UA_Int32 *out);
-static UA_INLINE UA_StatusCode
-UA_Client_readValueRankAttribute_async(
- UA_Client *client, const UA_NodeId nodeId,
- UA_ClientAsyncReadValueRankAttributeCallback callback, void *userdata,
- UA_UInt32 *reqId) {
- return __UA_Client_readAttribute_async(
- client, &nodeId, UA_ATTRIBUTEID_VALUERANK, &UA_TYPES[UA_TYPES_INT32],
- (UA_ClientAsyncServiceCallback)callback, userdata, reqId);
-}
-typedef void (*UA_ClientAsyncReadAccessLevelAttributeCallback)(UA_Client *client,
- void *userdata,
- UA_UInt32 requestId,
- UA_Byte *out);
-static UA_INLINE UA_StatusCode
-UA_Client_readAccessLevelAttribute_async(
- UA_Client *client, const UA_NodeId nodeId,
- UA_ClientAsyncReadAccessLevelAttributeCallback callback, void *userdata,
- UA_UInt32 *reqId) {
- return __UA_Client_readAttribute_async(
- client, &nodeId, UA_ATTRIBUTEID_ACCESSLEVEL, &UA_TYPES[UA_TYPES_BYTE],
- (UA_ClientAsyncServiceCallback)callback, userdata, reqId);
-}
-typedef void (*UA_ClientAsyncReadUserAccessLevelAttributeCallback)(UA_Client *client,
- void *userdata,
- UA_UInt32 requestId,
- UA_Byte *out);
-static UA_INLINE UA_StatusCode
-UA_Client_readUserAccessLevelAttribute_async(
- UA_Client *client, const UA_NodeId nodeId,
- UA_ClientAsyncReadUserAccessLevelAttributeCallback callback, void *userdata,
- UA_UInt32 *reqId) {
- return __UA_Client_readAttribute_async(
- client, &nodeId, UA_ATTRIBUTEID_USERACCESSLEVEL, &UA_TYPES[UA_TYPES_BYTE],
- (UA_ClientAsyncServiceCallback)callback, userdata, reqId);
-}
-typedef void (*UA_ClientAsyncReadMinimumSamplingIntervalAttributeCallback)(
- UA_Client *client, void *userdata, UA_UInt32 requestId, UA_Double *out);
-static UA_INLINE UA_StatusCode
-UA_Client_readMinimumSamplingIntervalAttribute_async(
- UA_Client *client, const UA_NodeId nodeId,
- UA_ClientAsyncReadMinimumSamplingIntervalAttributeCallback callback, void *userdata,
- UA_UInt32 *reqId) {
- return __UA_Client_readAttribute_async(
- client, &nodeId, UA_ATTRIBUTEID_MINIMUMSAMPLINGINTERVAL,
- &UA_TYPES[UA_TYPES_DOUBLE], (UA_ClientAsyncServiceCallback)callback, userdata,
- reqId);
-}
-typedef void (*UA_ClientAsyncReadHistorizingAttributeCallback)(UA_Client *client,
- void *userdata,
- UA_UInt32 requestId,
- UA_Boolean *out);
-static UA_INLINE UA_StatusCode
-UA_Client_readHistorizingAttribute_async(
- UA_Client *client, const UA_NodeId nodeId,
- UA_ClientAsyncReadHistorizingAttributeCallback callback, void *userdata,
- UA_UInt32 *reqId) {
- return __UA_Client_readAttribute_async(
- client, &nodeId, UA_ATTRIBUTEID_HISTORIZING, &UA_TYPES[UA_TYPES_BOOLEAN],
- (UA_ClientAsyncServiceCallback)callback, userdata, reqId);
-}
-typedef void (*UA_ClientAsyncReadExecutableAttributeCallback)(UA_Client *client,
- void *userdata,
- UA_UInt32 requestId,
- UA_Boolean *out);
-static UA_INLINE UA_StatusCode
-UA_Client_readExecutableAttribute_async(
- UA_Client *client, const UA_NodeId nodeId,
- UA_ClientAsyncReadExecutableAttributeCallback callback, void *userdata,
- UA_UInt32 *reqId) {
- return __UA_Client_readAttribute_async(
- client, &nodeId, UA_ATTRIBUTEID_EXECUTABLE, &UA_TYPES[UA_TYPES_BOOLEAN],
- (UA_ClientAsyncServiceCallback)callback, userdata, reqId);
-}
-typedef void (*UA_ClientAsyncReadUserExecutableAttributeCallback)(UA_Client *client,
- void *userdata,
- UA_UInt32 requestId,
- UA_Boolean *out);
-static UA_INLINE UA_StatusCode
-UA_Client_readUserExecutableAttribute_async(
- UA_Client *client, const UA_NodeId nodeId,
- UA_ClientAsyncReadUserExecutableAttributeCallback callback, void *userdata,
- UA_UInt32 *reqId) {
- return __UA_Client_readAttribute_async(
- client, &nodeId, UA_ATTRIBUTEID_USEREXECUTABLE, &UA_TYPES[UA_TYPES_BOOLEAN],
- (UA_ClientAsyncServiceCallback)callback, userdata, reqId);
-}
/**
* Write Attribute
* ^^^^^^^^^^^^^^ */
@@ -30244,26 +31926,20 @@ UA_Client_addMethodNode_async(UA_Client *client, const UA_NodeId requestedNewNod
* Misc Functionalities
* ^^^^^^^^^^^^^^^^^^^^ */
-UA_DEPRECATED UA_StatusCode UA_EXPORT
-__UA_Client_translateBrowsePathsToNodeIds_async(UA_Client *client, char *paths[],
- UA_UInt32 ids[], size_t pathSize,
- UA_ClientAsyncServiceCallback callback,
- void *userdata, UA_UInt32 *reqId);
-
-typedef void (*UA_ClientAsyncTranslateCallback)(
- UA_Client *client, void *userdata, UA_UInt32 requestId,
- UA_TranslateBrowsePathsToNodeIdsResponse *tr);
+/* typedef void (*UA_ClientAsyncTranslateCallback)( */
+/* UA_Client *client, void *userdata, UA_UInt32 requestId, */
+/* UA_TranslateBrowsePathsToNodeIdsResponse *tr); */
-UA_DEPRECATED UA_StatusCode UA_EXPORT
-UA_Cient_translateBrowsePathsToNodeIds_async(UA_Client *client, char **paths,
- UA_UInt32 *ids, size_t pathSize,
- UA_ClientAsyncTranslateCallback callback,
- void *userdata, UA_UInt32 *reqId);
+/* UA_DEPRECATED UA_StatusCode UA_EXPORT */
+/* UA_Cient_translateBrowsePathsToNodeIds_async(UA_Client *client, char **paths, */
+/* UA_UInt32 *ids, size_t pathSize, */
+/* UA_ClientAsyncTranslateCallback callback, */
+/* void *userdata, UA_UInt32 *reqId); */
_UA_END_DECLS
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/plugins/include/open62541/plugin/accesscontrol_default.h" ***********************************/
+/**** amalgamated original file "/plugins/include/open62541/plugin/accesscontrol_default.h" ****/
/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
* See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
@@ -30282,9 +31958,14 @@ typedef struct {
} UA_UsernamePasswordLogin;
/* Default access control. The log-in can be anonymous or username-password. A
- * logged-in user has all access rights. */
+ * logged-in user has all access rights.
+ *
+ * The certificate verification plugin lifecycle is moved to the access control
+ * system. So it is cleared up eventually together with the AccessControl. */
UA_EXPORT UA_StatusCode
-UA_AccessControl_default(UA_ServerConfig *config, UA_Boolean allowAnonymous,
+UA_AccessControl_default(UA_ServerConfig *config,
+ UA_Boolean allowAnonymous,
+ UA_CertificateVerification *verifyX509,
const UA_ByteString *userTokenPolicyUri,
size_t usernamePasswordLoginSize,
const UA_UsernamePasswordLogin *usernamePasswordLogin);
@@ -30292,7 +31973,7 @@ UA_AccessControl_default(UA_ServerConfig *config, UA_Boolean allowAnonymous,
_UA_END_DECLS
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/plugins/include/open62541/plugin/pki_default.h" ***********************************/
+/**** amalgamated original file "/plugins/include/open62541/plugin/pki_default.h" ****/
/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
* See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
@@ -30311,9 +31992,6 @@ UA_CertificateVerification_AcceptAll(UA_CertificateVerification *cv);
#ifdef UA_ENABLE_ENCRYPTION
-const unsigned char *
-UA_Bstrstr(const unsigned char *s1, size_t l1, const unsigned char *s2, size_t l2);
-
/* Accept certificates based on a trust-list and a revocation-list. Based on
* mbedTLS. */
UA_EXPORT UA_StatusCode
@@ -30338,7 +32016,7 @@ UA_CertificateVerification_CertFolders(UA_CertificateVerification *cv,
_UA_END_DECLS
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/plugins/include/open62541/plugin/log_stdout.h" ***********************************/
+/**** amalgamated original file "/plugins/include/open62541/plugin/log_stdout.h" ****/
/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
* See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
@@ -30369,7 +32047,7 @@ UA_EXPORT UA_Logger UA_Log_Stdout_withLevel(UA_LogLevel minlevel);
_UA_END_DECLS
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/plugins/include/open62541/plugin/nodestore_default.h" ***********************************/
+/**** amalgamated original file "/plugins/include/open62541/plugin/nodestore_default.h" ****/
/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
* See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
@@ -30400,7 +32078,7 @@ UA_Nodestore_ZipTree(UA_Nodestore *ns);
_UA_END_DECLS
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/plugins/include/open62541/server_config_default.h" ***********************************/
+/**** amalgamated original file "/plugins/include/open62541/server_config_default.h" ****/
/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
* See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
@@ -30519,11 +32197,13 @@ UA_ServerConfig_addNetworkLayerTCP(UA_ServerConfig *conf, UA_UInt16 portNumber,
* to use defaults.
* @param recvBufferSize The size in bytes for the network receive buffer.
* Pass 0 to use defaults.
+ * @param certificate certificate data. Pass NULL to disable WS security
+ * @param privateKey privateKey data. Pass NULL to disable WS security
*/
UA_EXPORT UA_StatusCode
UA_ServerConfig_addNetworkLayerWS(UA_ServerConfig *conf, UA_UInt16 portNumber,
- UA_UInt32 sendBufferSize, UA_UInt32 recvBufferSize);
+ UA_UInt32 sendBufferSize, UA_UInt32 recvBufferSize, const UA_ByteString* certificate, const UA_ByteString* privateKey);
#endif
/* Adds the security policy ``SecurityPolicy#None`` to the server. A
@@ -30583,6 +32263,21 @@ UA_ServerConfig_addSecurityPolicyBasic256Sha256(UA_ServerConfig *config,
const UA_ByteString *certificate,
const UA_ByteString *privateKey);
+/* Adds the security policy ``SecurityPolicy#Aes128Sha256RsaOaep`` to the server. A
+ * server certificate may be supplied but is optional.
+ *
+ * Certificate verification should be configured before calling this
+ * function. See PKI plugin.
+ *
+ * @param config The configuration to manipulate
+ * @param certificate The server certificate.
+ * @param privateKey The private key that corresponds to the certificate.
+ */
+UA_EXPORT UA_StatusCode
+UA_ServerConfig_addSecurityPolicyAes128Sha256RsaOaep(UA_ServerConfig *config,
+ const UA_ByteString *certificate,
+ const UA_ByteString *privateKey);
+
/* Adds all supported security policies and sets up certificate
* validation procedures.
*
@@ -30625,7 +32320,7 @@ UA_ServerConfig_addAllEndpoints(UA_ServerConfig *config);
_UA_END_DECLS
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/plugins/include/open62541/client_config_default.h" ***********************************/
+/**** amalgamated original file "/plugins/include/open62541/client_config_default.h" ****/
/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
* See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
@@ -30655,7 +32350,7 @@ UA_ClientConfig_setDefaultEncryption(UA_ClientConfig *config,
_UA_END_DECLS
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/plugins/include/open62541/plugin/securitypolicy_default.h" ***********************************/
+/**** amalgamated original file "/plugins/include/open62541/plugin/securitypolicy_default.h" ****/
/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
* See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
@@ -30694,12 +32389,40 @@ UA_SecurityPolicy_Basic256Sha256(UA_SecurityPolicy *policy,
const UA_ByteString localPrivateKey,
const UA_Logger *logger);
+UA_EXPORT UA_StatusCode
+UA_SecurityPolicy_Aes128Sha256RsaOaep(UA_SecurityPolicy *policy,
+ const UA_ByteString localCertificate,
+ const UA_ByteString localPrivateKey,
+ const UA_Logger *logger);
+
+#endif
+
+#ifdef UA_ENABLE_PUBSUB_ENCRYPTION
+
+UA_EXPORT UA_StatusCode
+UA_PubSubSecurityPolicy_Aes128Ctr(UA_PubSubSecurityPolicy *policy,
+ const UA_Logger *logger);
+UA_EXPORT UA_StatusCode
+UA_PubSubSecurityPolicy_Aes256Ctr(UA_PubSubSecurityPolicy *policy,
+ const UA_Logger *logger);
+
+#endif
+
+#ifdef UA_ENABLE_TPM2_SECURITY
+
+UA_EXPORT UA_StatusCode
+UA_PubSubSecurityPolicy_Aes128CtrTPM(UA_PubSubSecurityPolicy *policy, char *userpin, unsigned long slotId,
+ char *encryptionKeyLabel, char *signingKeyLabel, const UA_Logger *logger);
+UA_EXPORT UA_StatusCode
+UA_PubSubSecurityPolicy_Aes256CtrTPM(UA_PubSubSecurityPolicy *policy, char *userpin, unsigned long slotId,
+ char *encryptionKeyLabel, char *signingKeyLabel, const UA_Logger *logger);
+
#endif
_UA_END_DECLS
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/plugins/include/open62541/plugin/log_syslog.h" ***********************************/
+/**** amalgamated original file "/plugins/include/open62541/plugin/log_syslog.h" ****/
/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
* See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
@@ -30713,7 +32436,7 @@ _UA_BEGIN_DECLS
/* Syslog-logging is available only for Linux/Unices.
*
- * open62541 log-levels are translated to syslog-levels as follows:
+ * open62541 log levels are translated to syslog levels as follows:
*
* UA_LOGLEVEL_TRACE => not available for syslog
* UA_LOGLEVEL_DEBUG => LOG_DEBUG
@@ -30740,7 +32463,50 @@ UA_Log_Syslog(void);
_UA_END_DECLS
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/plugins/include/open62541/plugin/historydata/history_data_backend.h" ***********************************/
+/**** amalgamated original file "/plugins/include/open62541/plugin/create_certificate.h" ****/
+
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Copyright 2021 (c) Christian von Arnim, ISW University of Stuttgart (for VDW and umati)
+ */
+
+
+
+_UA_BEGIN_DECLS
+
+#ifdef UA_ENABLE_ENCRYPTION
+typedef enum {
+ UA_CERTIFICATEFORMAT_DER,
+ UA_CERTIFICATEFORMAT_PEM
+} UA_CertificateFormat;
+
+/**
+ * Create a self-signed certificate
+ *
+ * It is recommended to store the generated certificate on disk for reuse, so the
+ * application can be recognized across several executions.
+ *
+ * \param subject Elements for the subject,
+ * e.g. ["C=DE", "O=SampleOrganization", "CN=Open62541Server@localhost"]
+ * \param subjectAltName Elements for SubjectAltName,
+ * e.g. ["DNS:localhost", "URI:urn:open62541.server.application"]
+ * \param keySizeBits Size of the generated key in bits. If set to 0, the maximum key
+ * size is used. Possible values are: [0, 1024 (deprecated), 2048, 4096]
+ */
+UA_StatusCode UA_EXPORT
+UA_CreateCertificate(const UA_Logger *logger,
+ const UA_String *subject, size_t subjectSize,
+ const UA_String *subjectAltName, size_t subjectAltNameSize,
+ size_t keySizeBits, UA_CertificateFormat certFormat,
+ UA_ByteString *outPrivateKey, UA_ByteString *outCertificate);
+#endif
+
+_UA_END_DECLS
+
+
+/**** amalgamated original file "/plugins/include/open62541/plugin/historydata/history_data_backend.h" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -31030,7 +32796,7 @@ struct UA_HistoryDataBackend {
_UA_END_DECLS
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/plugins/include/open62541/plugin/historydata/history_data_gathering.h" ***********************************/
+/**** amalgamated original file "/plugins/include/open62541/plugin/historydata/history_data_gathering.h" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -31149,7 +32915,7 @@ struct UA_HistoryDataGathering {
_UA_END_DECLS
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/plugins/include/open62541/plugin/historydata/history_database_default.h" ***********************************/
+/**** amalgamated original file "/plugins/include/open62541/plugin/historydata/history_database_default.h" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -31169,7 +32935,7 @@ UA_HistoryDatabase_default(UA_HistoryDataGathering gathering);
_UA_END_DECLS
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/plugins/include/open62541/plugin/historydata/history_data_gathering_default.h" ***********************************/
+/**** amalgamated original file "/plugins/include/open62541/plugin/historydata/history_data_gathering_default.h" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -31188,7 +32954,7 @@ UA_HistoryDataGathering_Default(size_t initialNodeIdStoreSize);
_UA_END_DECLS
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/plugins/include/open62541/plugin/historydata/history_data_backend_memory.h" ***********************************/
+/**** amalgamated original file "/plugins/include/open62541/plugin/historydata/history_data_backend_memory.h" ****/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -31207,12 +32973,12 @@ UA_HistoryDataBackend UA_EXPORT
UA_HistoryDataBackend_Memory(size_t initialNodeIdStoreSize, size_t initialDataStoreSize);
void UA_EXPORT
-UA_HistoryDataBackend_Memory_deleteMembers(UA_HistoryDataBackend *backend);
+UA_HistoryDataBackend_Memory_clear(UA_HistoryDataBackend *backend);
_UA_END_DECLS
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/include/open62541/network_tcp.h" ***********************************/
+/**** amalgamated original file "/include/open62541/network_tcp.h" ****/
/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
* See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
@@ -31236,23 +33002,26 @@ _UA_BEGIN_DECLS
* @return Returns the network layer instance */
UA_ServerNetworkLayer UA_EXPORT
UA_ServerNetworkLayerTCP(UA_ConnectionConfig config, UA_UInt16 port,
- UA_UInt16 maxConnections, UA_Logger *logger);
+ UA_UInt16 maxConnections);
+/* Open a non-blocking client TCP socket. The connection might not be fully
+ * opened yet. Drop into the _poll function withe a timeout to complete the
+ * connection. */
UA_Connection UA_EXPORT
-UA_ClientConnectionTCP(UA_ConnectionConfig config, const UA_String endpointUrl,
- UA_UInt32 timeout, UA_Logger *logger);
+UA_ClientConnectionTCP_init(UA_ConnectionConfig config, const UA_String endpointUrl,
+ UA_UInt32 timeout, const UA_Logger *logger);
+/* Wait for a half-opened connection to fully open. Returns UA_STATUSCODE_GOOD
+ * even if the timeout was hit. Returns UA_STATUSCODE_BADDISCONNECT if the
+ * connection is lost. */
UA_StatusCode UA_EXPORT
-UA_ClientConnectionTCP_poll(UA_Client *client, void *data, UA_UInt32 timeout);
-
-UA_Connection UA_EXPORT
-UA_ClientConnectionTCP_init(UA_ConnectionConfig config, const UA_String endpointUrl,
- UA_UInt32 timeout, UA_Logger *logger);
+UA_ClientConnectionTCP_poll(UA_Connection *connection, UA_UInt32 timeout,
+ const UA_Logger *logger);
_UA_END_DECLS
-/*********************************** amalgamated original file "/home/pdie/sonstiges/qtopcua/repos/open62541/include/open62541/architecture_functions.h" ***********************************/
+/**** amalgamated original file "/include/open62541/architecture_functions.h" ****/
/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
* See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
@@ -31261,75 +33030,27 @@ _UA_END_DECLS
*/
/*
- * This header has all the functions that are architecture dependent. The declaration is behind a ifndef since
- * they can be previously defined in the ua_architecture.h which include this files at the end
+ * This header has all the functions that are architecture dependent. The
+ * declaration is behind an ifndef since they can be previously defined in the
+ * ua_architecture.h which include this files at the end
*/
_UA_BEGIN_DECLS
-/*
- * Allocation functions
- */
-
-#ifndef UA_malloc
-void* UA_malloc(size_t size); //allocate memory in the heap with size bytes
-#endif
-
-#ifndef UA_calloc
-void* UA_calloc(size_t num, size_t size); //allocate memory in the heap with size*num bytes and set the memory to zero
-#endif
-
-#ifndef UA_realloc
-void* UA_realloc(void *ptr, size_t new_size);//re-allocate memory in the heap with new_size bytes from previously allocated memory ptr
-#endif
-
-#ifndef UA_free
-void UA_free(void* ptr); //de-allocate memory previously allocated with UA_malloc, UA_calloc or UA_realloc
-#endif
-
-#ifndef UA_alloca
-# if defined(__GNUC__) || defined(__clang__)
-# define UA_alloca(size) __builtin_alloca (size)
-# elif defined(_WIN32)
-# define UA_alloca(SIZE) _alloca(SIZE)
-# else
-# include <alloca.h>
-# define UA_alloca(SIZE) alloca(SIZE)
-# endif
-#endif
-
-#ifndef UA_STACKARRAY
-/* Stack-allocation of memory. Use C99 variable-length arrays if possible.
- * Otherwise revert to alloca. Note that alloca is not supported on some
- * plattforms. */
-# if defined(__GNUC__) || defined(__clang__)
-# define UA_STACKARRAY(TYPE, NAME, SIZE) TYPE NAME[SIZE]
-# else
-# define UA_STACKARRAY(TYPE, NAME, SIZE) \
- TYPE *NAME = (TYPE*)UA_alloca(sizeof(TYPE) * SIZE)
-# endif
-#endif
-
-/*
- * Sleep function
- */
-
+/* Sleep function */
#ifndef UA_sleep_ms
int UA_sleep_ms(unsigned int miliSeconds); //suspend the thread for a certain amount of mili seconds
#endif
-/*
- * Socket functions
- */
-
+/* Socket functions */
#ifndef UA_send
ssize_t UA_send(UA_SOCKET sockfd, const void *buf, size_t len, int flags); //equivalent to posix send implementation
#endif
#ifndef UA_sendto
-ssize_t sendto(UA_SOCKET sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen); //equivalent to posix sendto implementation
+ssize_t UA_sendto(UA_SOCKET sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen); //equivalent to posix sendto implementation
#endif
#ifndef UA_select
@@ -31341,7 +33062,11 @@ ssize_t UA_recv(UA_SOCKET sockfd, void *buf, size_t len, int flags); //equivalen
#endif
#ifndef UA_recvfrom
-ssize_t recvfrom(UA_SOCKET sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
+ssize_t UA_recvfrom(UA_SOCKET sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);//equivalent to posix recvfrom implementation
+#endif
+
+#ifndef UA_recvmsg
+ssize_t UA_recvmsg(int sockfd, struct msghdr *msg, int flags);//equivalent to posix recvmsg implementation
#endif
#ifndef UA_shutdown
@@ -31410,6 +33135,10 @@ unsigned int UA_socket_set_blocking(UA_SOCKET sockfd);//set a socket as blocking
unsigned int UA_socket_set_nonblocking(UA_SOCKET sockfd);//set a socket as non-blocking. Returns 0 if OK, other value otherwise
#endif
+#ifndef UA_ioctl
+int UA_ioctl(int fildes, int request, ...);//equivalent to posix ioctl implementation
+#endif
+
#ifndef UA_getsockopt
int UA_getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen); //equivalent to posix getsockopt implementation. Only in non windows architectures
#endif
@@ -31419,7 +33148,7 @@ int UA_setsockopt(int sockfd, int level, int optname, const void *optval, sockle
#endif
#ifndef UA_freeaddrinfo
-void UA_freeaddrinfo(struct addrinfo *res);//equivalent to posix freeaddrinfo implementatio
+void UA_freeaddrinfo(struct addrinfo *res);//equivalent to posix freeaddrinfo implementation
#endif
#ifndef UA_gethostname
@@ -31438,17 +33167,16 @@ void UA_initialize_architecture_network(void);//initializes all needed for using
void UA_deinitialize_architecture_network(void);//de-initializes the network interfaces
#endif
-/*
- * Print function
- */
+/* Print function */
#ifndef UA_snprintf
int UA_snprintf(char* pa_stream, size_t pa_size, const char* pa_format, ...); //prints text to output
#endif
-/*
- * Access to file function
- */
+#ifndef UA_strncasecmp
+int UA_strncasecmp(const char* s1, const char* s2, size_t n);
+#endif
+/* Access to file function */
#ifndef UA_access
int UA_access(const char *pathname, int mode); //equivalent implementation of https://linux.die.net/man/2/access
#endif
diff --git a/src/3rdparty/open62541/patches/0001-feat-plugin-Add-OpenSSL-3.0-support-5349.patch b/src/3rdparty/open62541/patches/0001-feat-plugin-Add-OpenSSL-3.0-support-5349.patch
new file mode 100644
index 0000000..a20d56b
--- /dev/null
+++ b/src/3rdparty/open62541/patches/0001-feat-plugin-Add-OpenSSL-3.0-support-5349.patch
@@ -0,0 +1,282 @@
+From 7dbde94a813acac866e7964ecc868d2f70076510 Mon Sep 17 00:00:00 2001
+From: Bin Lan <Bin.Lan@windriver.com>
+Date: Tue, 27 Sep 2022 21:45:38 +0800
+Subject: [PATCH] feat(plugin): Add OpenSSL 3.0 support (#5349)
+
+* Add OpenSSL3.0 support
+
+This change set adds a new function UA_OpenSSL_RSA_Key_Size() to get
+the RSA key size, re-writes the function
+UA_Openssl_RSA_Private_Decrypt() by using the high level APIs of
+OpenSSL3.0, add a new function UA_RSA_Generate_Key() to generate
+a RSA key.
+
+No build warning with OpenSSL3.0 and OpenSSL1.1.1f.
+
+* Build & Test with OpenSSL3.0 in Ubuntu22.04
+---
+ .github/workflows/build_ubuntu2204.yml | 29 ++++++++
+ .../openssl/securitypolicy_openssl_common.c | 68 ++++++++++++++-----
+ .../openssl/ua_openssl_create_certificate.c | 28 +++++++-
+ 3 files changed, 104 insertions(+), 21 deletions(-)
+ create mode 100644 .github/workflows/build_ubuntu2204.yml
+
+diff --git a/.github/workflows/build_ubuntu2204.yml b/.github/workflows/build_ubuntu2204.yml
+new file mode 100644
+index 00000000..216c0665
+--- /dev/null
++++ b/.github/workflows/build_ubuntu2204.yml
+@@ -0,0 +1,29 @@
++name: Linux Build & Test with OpenSSL3.0
++
++on: [push, pull_request]
++
++jobs:
++ build:
++ strategy:
++ fail-fast: false
++ matrix:
++ include:
++ - build_name: "Encryption (OpenSSL3.0) Build & Unit Tests (gcc)"
++ cmd_deps: sudo apt-get install -y -qq openssl
++ cmd_action: unit_tests_encryption OPENSSL
++ name: ${{matrix.build_name}}
++ runs-on: ubuntu-22.04
++ steps:
++ - uses: actions/checkout@v2
++ with:
++ submodules: true
++ - name: Install Dependencies
++ run: |
++ sudo apt-get update
++ sudo apt-get install -y -qq python3-sphinx graphviz check
++ ${{ matrix.cmd_deps }}
++ - name: ${{matrix.build_name}}
++ run: source tools/ci.sh && ${{matrix.cmd_action}}
++ env:
++ ETHERNET_INTERFACE: eth0
++
+diff --git a/plugins/crypto/openssl/securitypolicy_openssl_common.c b/plugins/crypto/openssl/securitypolicy_openssl_common.c
+index 3b8d5711..78118ed2 100644
+--- a/plugins/crypto/openssl/securitypolicy_openssl_common.c
++++ b/plugins/crypto/openssl/securitypolicy_openssl_common.c
+@@ -4,6 +4,7 @@
+ *
+ * Copyright 2020 (c) Wind River Systems, Inc.
+ * Copyright 2020 (c) basysKom GmbH
++ * Copyright 2022 (c) Wind River Systems, Inc.
+ */
+
+ /*
+@@ -30,6 +31,8 @@ modification history
+ #include "ua_openssl_version_abstraction.h"
+
+ #define SHA1_DIGEST_LENGTH 20 /* 160 bits */
++#define RSA_DECRYPT_BUFFER_LENGTH 2048 /* bytes */
++
+
+ /** P_SHA256 Context */
+ typedef struct UA_Openssl_P_SHA256_Ctx_ {
+@@ -73,6 +76,14 @@ UA_Openssl_Init (void) {
+ #endif
+ }
+
++static int UA_OpenSSL_RSA_Key_Size (EVP_PKEY * key){
++#if (OPENSSL_VERSION_NUMBER >= 0x30000000L)
++ return EVP_PKEY_get_size (key);
++#else
++ return RSA_size (get_pkey_rsa(key));
++#endif
++}
++
+ /* UA_copyCertificate - allocalte the buffer, copy the certificate and
+ * add a NULL to the end
+ */
+@@ -192,8 +203,8 @@ UA_Openssl_X509_GetCertificateThumbprint (const UA_ByteString * certficate,
+ }
+
+ static UA_StatusCode
+-UA_Openssl_RSA_Private_Decrypt (UA_ByteString * data,
+- EVP_PKEY * privateKey,
++UA_Openssl_RSA_Private_Decrypt (UA_ByteString * data,
++ EVP_PKEY * privateKey,
+ UA_Int16 padding) {
+ if (data == NULL || privateKey == NULL) {
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+@@ -203,27 +214,49 @@ UA_Openssl_RSA_Private_Decrypt (UA_ByteString * data,
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+ }
+
+- UA_Int32 keySize = RSA_size(get_pkey_rsa(privateKey));
++ size_t keySize = (size_t) UA_OpenSSL_RSA_Key_Size (privateKey);
+ size_t cipherOffset = 0;
+ size_t outOffset = 0;
+- unsigned char buf[2048];
+- UA_Int32 decryptedBytes;
++ unsigned char buf[RSA_DECRYPT_BUFFER_LENGTH];
++ size_t decryptedBytes;
++ EVP_PKEY_CTX * ctx;
++ int opensslRet;
++
++ ctx = EVP_PKEY_CTX_new (privateKey, NULL);
++ if (ctx == NULL) {
++ return UA_STATUSCODE_BADOUTOFMEMORY;
++ }
++ opensslRet = EVP_PKEY_decrypt_init (ctx);
++ if (opensslRet != 1)
++ {
++ EVP_PKEY_CTX_free (ctx);
++ return UA_STATUSCODE_BADINTERNALERROR;
++ }
++ opensslRet = EVP_PKEY_CTX_set_rsa_padding (ctx, padding);
++ if (opensslRet != 1) {
++ EVP_PKEY_CTX_free (ctx);
++ return UA_STATUSCODE_BADINTERNALERROR;
++ }
+
+ while (cipherOffset < data->length) {
+- decryptedBytes = RSA_private_decrypt (keySize,
+- data->data + cipherOffset, /* what to decrypt */
++ decryptedBytes = RSA_DECRYPT_BUFFER_LENGTH;
++ opensslRet = EVP_PKEY_decrypt (ctx,
+ buf, /* where to decrypt */
+- get_pkey_rsa(privateKey), /* private key */
+- padding
++ &decryptedBytes,
++ data->data + cipherOffset, /* what to decrypt */
++ keySize
+ );
+- if (decryptedBytes < 0) {
++ if (opensslRet != 1) {
++ EVP_PKEY_CTX_free (ctx);
+ return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
+ }
+- memcpy(data->data + outOffset, buf, (size_t) decryptedBytes);
++ (void) memcpy(data->data + outOffset, buf, decryptedBytes);
+ cipherOffset += (size_t) keySize;
+- outOffset += (size_t) decryptedBytes;
++ outOffset += decryptedBytes;
+ }
+ data->length = outOffset;
++ EVP_PKEY_CTX_free (ctx);
++
+ return UA_STATUSCODE_GOOD;
+ }
+
+@@ -249,7 +282,6 @@ UA_Openssl_RSA_Public_Encrypt (const UA_ByteString * message,
+ size_t encryptedPos = 0;
+ size_t bytesToEncrypt = 0;
+ size_t encryptedBlockSize = 0;
+- RSA * rsa = NULL;
+ size_t keySize = 0;
+
+ evpPublicKey = X509_get_pubkey (publicX509);
+@@ -274,8 +306,8 @@ UA_Openssl_RSA_Public_Encrypt (const UA_ByteString * message,
+ }
+
+ /* get the encrypted block size */
+- rsa = get_pkey_rsa (evpPublicKey);
+- keySize = (size_t) RSA_size (rsa);
++
++ keySize = (size_t) UA_OpenSSL_RSA_Key_Size (evpPublicKey);
+ if (keySize == 0) {
+ ret = UA_STATUSCODE_BADINTERNALERROR;
+ goto errout;
+@@ -435,8 +467,8 @@ UA_Openssl_RSA_Public_GetKeyLength (X509 * publicKeyX509,
+ if (evpKey == NULL) {
+ return UA_STATUSCODE_BADINTERNALERROR;
+ }
+- RSA * rsa = get_pkey_rsa (evpKey);
+- *keyLen = RSA_size(rsa);
++ *keyLen = UA_OpenSSL_RSA_Key_Size (evpKey);
++
+ EVP_PKEY_free (evpKey);
+
+ return UA_STATUSCODE_GOOD;
+@@ -448,7 +480,7 @@ UA_Openssl_RSA_Private_GetKeyLength (EVP_PKEY * privateKey,
+ if (privateKey == NULL) {
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+ }
+- *keyLen = RSA_size(get_pkey_rsa(privateKey));
++ *keyLen = UA_OpenSSL_RSA_Key_Size (privateKey);
+
+ return UA_STATUSCODE_GOOD;
+ }
+diff --git a/plugins/crypto/openssl/ua_openssl_create_certificate.c b/plugins/crypto/openssl/ua_openssl_create_certificate.c
+index 4b07e886..0ea63f95 100644
+--- a/plugins/crypto/openssl/ua_openssl_create_certificate.c
++++ b/plugins/crypto/openssl/ua_openssl_create_certificate.c
+@@ -3,6 +3,7 @@
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Copyright 2021 (c) Christian von Arnim, ISW University of Stuttgart (for VDW and umati)
++ * Copyright 2022 (c) Wind River Systems, Inc.
+ *
+ */
+
+@@ -81,6 +82,16 @@ add_x509V3ext(X509 *x509, int nid, const char *value) {
+ return UA_STATUSCODE_GOOD;
+ }
+
++#if (OPENSSL_VERSION_NUMBER >= 0x30000000L)
++
++/* generate the RSA key */
++
++static EVP_PKEY * UA_RSA_Generate_Key (size_t keySizeBits){
++ return EVP_RSA_gen(keySizeBits);
++}
++
++#endif
++
+ UA_StatusCode
+ UA_CreateCertificate(const UA_Logger *logger,
+ const UA_String *subject, size_t subjectSize,
+@@ -109,11 +120,18 @@ UA_CreateCertificate(const UA_Logger *logger,
+
+ UA_StatusCode errRet = UA_STATUSCODE_GOOD;
+
++ X509 *x509 = X509_new();
++
++#if (OPENSSL_VERSION_NUMBER >= 0x30000000L)
++ EVP_PKEY *pkey = UA_RSA_Generate_Key(keySizeBits);
++ if((pkey == NULL) || (x509 == NULL)) {
++ errRet = UA_STATUSCODE_BADOUTOFMEMORY;
++ goto cleanup;
++ }
++#else
+ BIGNUM *exponent = BN_new();
+ EVP_PKEY *pkey = EVP_PKEY_new();
+- X509 *x509 = X509_new();
+ RSA *rsa = RSA_new();
+-
+ if(!pkey || !x509 || !exponent || !rsa) {
+ errRet = UA_STATUSCODE_BADOUTOFMEMORY;
+ goto cleanup;
+@@ -145,6 +163,8 @@ UA_CreateCertificate(const UA_Logger *logger,
+ /* rsa will be freed by pkey */
+ rsa = NULL;
+
++#endif /* end of OPENSSL_VERSION_NUMBER >= 0x30000000L */
++
+ /* x509v3 has version 2
+ * (https://www.openssl.org/docs/man1.1.0/man3/X509_set_version.html) */
+ if(X509_set_version(x509, 2) != 1) {
+@@ -351,12 +371,14 @@ UA_CreateCertificate(const UA_Logger *logger,
+
+ cleanup:
+ UA_String_clear(&fullAltSubj);
++#if (OPENSSL_VERSION_NUMBER < 0x30000000L)
+ RSA_free(rsa);
++ BN_free(exponent);
++#endif
+ X509_free(x509);
+ EVP_PKEY_free(pkey);
+ BIO_free(memCert);
+ BIO_free(memPKey);
+- BN_free(exponent);
+ return errRet;
+ }
+
+--
+2.34.1
+
diff --git a/src/3rdparty/open62541/patches/0001-fix-core-use-of-compound-volatile-operations-depreca.patch b/src/3rdparty/open62541/patches/0001-fix-core-use-of-compound-volatile-operations-depreca.patch
deleted file mode 100644
index ad2d07f..0000000
--- a/src/3rdparty/open62541/patches/0001-fix-core-use-of-compound-volatile-operations-depreca.patch
+++ /dev/null
@@ -1,91 +0,0 @@
-From 464966135e5cc7af30d9a3f6bdc81be937b95ac3 Mon Sep 17 00:00:00 2001
-From: Marc Mutz <marc.mutz@qt.io>
-Date: Fri, 1 Jul 2022 09:53:55 +0200
-Subject: [PATCH] fix(core): use of compound volatile operations (deprecated in
- C++20)
-
-C++20 deprecated compound volatile operations, so this code fails to
-compile in C++20 mode due to -Werror.
-
-Fix by separating loading and saving of the value, which, in the case
-of architecture_definitions.h, even reduces the per-operation loads
-from two to one.
-
-Fixes: #5247
----
- include/open62541/architecture_definitions.h | 24 +++++++++++++-------
- include/open62541/util.h | 2 +-
- 2 files changed, 17 insertions(+), 9 deletions(-)
-
-diff --git a/include/open62541/architecture_definitions.h b/include/open62541/architecture_definitions.h
-index f22f401d..15a21505 100644
---- a/include/open62541/architecture_definitions.h
-+++ b/include/open62541/architecture_definitions.h
-@@ -456,8 +456,10 @@ UA_atomic_addUInt32(volatile uint32_t *addr, uint32_t increase) {
- return __sync_add_and_fetch(addr, increase);
- #endif
- #else
-- *addr += increase;
-- return *addr;
-+ uint32_t accu = *addr;
-+ accu += increase;
-+ *addr = accu;
-+ return accu;
- #endif
- }
-
-@@ -470,8 +472,10 @@ UA_atomic_addSize(volatile size_t *addr, size_t increase) {
- return __sync_add_and_fetch(addr, increase);
- #endif
- #else
-- *addr += increase;
-- return *addr;
-+ size_t accu = *addr;
-+ accu += increase;
-+ *addr = accu;
-+ return accu;
- #endif
- }
-
-@@ -484,8 +488,10 @@ UA_atomic_subUInt32(volatile uint32_t *addr, uint32_t decrease) {
- return __sync_sub_and_fetch(addr, decrease);
- #endif
- #else
-- *addr -= decrease;
-- return *addr;
-+ uint32_t accu = *addr;
-+ accu -= decrease;
-+ *addr = accu;
-+ return accu;
- #endif
- }
-
-@@ -498,8 +504,10 @@ UA_atomic_subSize(volatile size_t *addr, size_t decrease) {
- return __sync_sub_and_fetch(addr, decrease);
- #endif
- #else
-- *addr -= decrease;
-- return *addr;
-+ size_t accu = *addr;
-+ accu -= decrease;
-+ *addr = accu;
-+ return accu;
- #endif
- }
-
-diff --git a/include/open62541/util.h b/include/open62541/util.h
-index 79e49f20..9f3b5fea 100644
---- a/include/open62541/util.h
-+++ b/include/open62541/util.h
-@@ -213,7 +213,7 @@ UA_constantTimeEqual(const void *ptr1, const void *ptr2, size_t length) {
- volatile UA_Byte c = 0;
- for(size_t i = 0; i < length; ++i) {
- UA_Byte x = a[i], y = b[i];
-- c |= x ^ y;
-+ c = c | (x ^ y);
- }
- return !c;
- }
---
-2.25.1
-
diff --git a/src/opcua/configure.cmake b/src/opcua/configure.cmake
index 5c97db9..91e679f 100644
--- a/src/opcua/configure.cmake
+++ b/src/opcua/configure.cmake
@@ -53,7 +53,7 @@ if (INPUT_open62541 STREQUAL "system")
}
/* Clean up */
- UA_Variant_deleteMembers(&value);
+ UA_Variant_clear(&value);
UA_Client_delete(client); /* Disconnects the client internally */
return status;
}")
diff --git a/src/opcua/doc/src/qtopcua.qdoc b/src/opcua/doc/src/qtopcua.qdoc
index 3db23af..211a191 100644
--- a/src/opcua/doc/src/qtopcua.qdoc
+++ b/src/opcua/doc/src/qtopcua.qdoc
@@ -37,7 +37,7 @@
Currently, the following implementations are supported:
\list
- \li Open62541 v1.1, MPLv2
+ \li Open62541 v1.3.1, MPLv2
\li Unified Automation C++ SDK (UACpp), Commercial
\endlist
@@ -434,8 +434,8 @@
The Open62541 plugin is built by default from the included 3rd party sources and has no external dependencies.
The open62541 library uses OpenSSL for security. If the OpenSSL library is detected during configuration,
security is enabled for the tests and the open62541 backend.
- The Open62541 source and header files bundled with Qt OPC UA have been generated from the open62541 1.1
- commit e941fc23b0 using the following commands:
+ The Open62541 source and header files bundled with Qt OPC UA have been generated from the open62541 1.3
+ commit 3fc6870a using the following commands:
\code
cmake -DUA_ENABLE_AMALGAMATION=ON -DUA_AMALGAMATION_ARCHITECTURES="win32;posix" -DUA_ENABLE_SUBSCRIPTIONS_EVENTS=ON -DUA_ENABLE_HISTORIZING=ON -DUA_ENABLE_EXPERIMENTAL_HISTORIZING=ON
@@ -448,7 +448,7 @@
cmake </path/to/qtopcua> -DINPUT_open62541=no
\encode
- In case you want to build a custom version of the Open62541 plugin, Open62541 1.1 (e941fc23b0) built with the same options as above is required.
+ In case you want to build a custom version of the Open62541 plugin, Open62541 1.3 (3fc6870a) built with the same options as above is required.
The following options must be passed to cmake when building with open62541 installed to a custom location:
diff --git a/src/plugins/opcua/open62541/CMakeLists.txt b/src/plugins/opcua/open62541/CMakeLists.txt
index d55858f..dc26a5c 100644
--- a/src/plugins/opcua/open62541/CMakeLists.txt
+++ b/src/plugins/opcua/open62541/CMakeLists.txt
@@ -56,7 +56,6 @@ qt_internal_extend_target(QOpen62541Plugin CONDITION QT_FEATURE_open62541 AND NO
# special case begin
qt_internal_extend_target(QOpen62541Plugin CONDITION QT_FEATURE_open62541_security AND WrapOpenSSL_FOUND AND QT_FEATURE_open62541 AND NOT QT_FEATURE_system_open62541
DEFINES
- UA_ENABLE_ENCRYPTION
UA_ENABLE_ENCRYPTION_OPENSSL
LIBRARIES
WrapOpenSSL::WrapOpenSSL
@@ -91,7 +90,8 @@ if (QT_FEATURE_open62541 AND NOT QT_FEATURE_system_open62541)
set_source_files_properties(../../../3rdparty/open62541/open62541.c PROPERTIES
LANGUAGE CXX
SKIP_PRECOMPILE_HEADERS ON
- COMPILE_OPTIONS "/Zc:strictStrings-;/permissive;/wd2362")
+ #COMPILE_OPTIONS "/Zc:strictStrings-;/permissive")
+ COMPILE_OPTIONS "/Zc:strictStrings-;/permissive;/wd4200")
endif()
endif()
# special case end
diff --git a/src/plugins/opcua/open62541/qopen62541.h b/src/plugins/opcua/open62541/qopen62541.h
index aed1262..a4f63df 100644
--- a/src/plugins/opcua/open62541/qopen62541.h
+++ b/src/plugins/opcua/open62541/qopen62541.h
@@ -11,6 +11,8 @@
#elif defined(__GNUC__) //includes mingw
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
+#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
+#pragma GCC diagnostic ignored "-Wmissing-braces"
#elif defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-parameter"
diff --git a/src/plugins/opcua/open62541/qopen62541backend.cpp b/src/plugins/opcua/open62541/qopen62541backend.cpp
index f62ad6c..8714e7a 100644
--- a/src/plugins/opcua/open62541/qopen62541backend.cpp
+++ b/src/plugins/opcua/open62541/qopen62541backend.cpp
@@ -176,7 +176,7 @@ void Open62541AsyncBackend::writeAttributes(quint64 handle, UA_NodeId id, QOpcUa
void Open62541AsyncBackend::enableMonitoring(quint64 handle, UA_NodeId id, QOpcUa::NodeAttributes attr, const QOpcUaMonitoringParameters &settings)
{
- UaDeleter<UA_NodeId> nodeIdDeleter(&id, UA_NodeId_deleteMembers);
+ UaDeleter<UA_NodeId> nodeIdDeleter(&id, UA_NodeId_clear);
QOpen62541Subscription *usedSubscription = nullptr;
@@ -328,7 +328,7 @@ void Open62541AsyncBackend::resolveBrowsePath(quint64 handle, UA_NodeId startNod
UA_TranslateBrowsePathsToNodeIdsRequest req;
UA_TranslateBrowsePathsToNodeIdsRequest_init(&req);
UaDeleter<UA_TranslateBrowsePathsToNodeIdsRequest> requestDeleter(
- &req,UA_TranslateBrowsePathsToNodeIdsRequest_deleteMembers);
+ &req,UA_TranslateBrowsePathsToNodeIdsRequest_clear);
req.browsePathsSize = 1;
req.browsePaths = UA_BrowsePath_new();
@@ -466,7 +466,7 @@ void Open62541AsyncBackend::readNodeAttributes(const QList<QOpcUaReadItem> &node
UA_ReadRequest req;
UA_ReadRequest_init(&req);
- UaDeleter<UA_ReadRequest> requestDeleter(&req, UA_ReadRequest_deleteMembers);
+ UaDeleter<UA_ReadRequest> requestDeleter(&req, UA_ReadRequest_clear);
req.nodesToReadSize = nodesToRead.size();
req.nodesToRead = static_cast<UA_ReadValueId *>(UA_Array_new(nodesToRead.size(), &UA_TYPES[UA_TYPES_READVALUEID]));
@@ -503,7 +503,7 @@ void Open62541AsyncBackend::writeNodeAttributes(const QList<QOpcUaWriteItem> &no
UA_WriteRequest req;
UA_WriteRequest_init(&req);
- UaDeleter<UA_WriteRequest> requestDeleter(&req, UA_WriteRequest_deleteMembers);
+ UaDeleter<UA_WriteRequest> requestDeleter(&req, UA_WriteRequest_clear);
req.nodesToWriteSize = nodesToWrite.size();
req.nodesToWrite = static_cast<UA_WriteValue *>(UA_Array_new(nodesToWrite.size(), &UA_TYPES[UA_TYPES_WRITEVALUE]));
@@ -600,7 +600,7 @@ void Open62541AsyncBackend::addNode(const QOpcUaAddNodeItem &nodeToAdd)
{
UA_AddNodesRequest req;
UA_AddNodesRequest_init(&req);
- UaDeleter<UA_AddNodesRequest> requestDeleter(&req, UA_AddNodesRequest_deleteMembers);
+ UaDeleter<UA_AddNodesRequest> requestDeleter(&req, UA_AddNodesRequest_clear);
req.nodesToAddSize = 1;
req.nodesToAdd = UA_AddNodesItem_new();
UA_AddNodesItem_init(req.nodesToAdd);
@@ -644,7 +644,7 @@ void Open62541AsyncBackend::deleteNode(const QString &nodeId, bool deleteTargetR
{
UA_DeleteNodesRequest request;
UA_DeleteNodesRequest_init(&request);
- UaDeleter<UA_DeleteNodesRequest> requestDeleter(&request, UA_DeleteNodesRequest_deleteMembers);
+ UaDeleter<UA_DeleteNodesRequest> requestDeleter(&request, UA_DeleteNodesRequest_clear);
request.nodesToDeleteSize = 1;
request.nodesToDelete = UA_DeleteNodesItem_new();
@@ -673,7 +673,7 @@ void Open62541AsyncBackend::addReference(const QOpcUaAddReferenceItem &reference
{
UA_AddReferencesRequest request;
UA_AddReferencesRequest_init(&request);
- UaDeleter<UA_AddReferencesRequest> requestDeleter(&request, UA_AddReferencesRequest_deleteMembers);
+ UaDeleter<UA_AddReferencesRequest> requestDeleter(&request, UA_AddReferencesRequest_clear);
request.referencesToAddSize = 1;
request.referencesToAdd = UA_AddReferencesItem_new();
@@ -712,7 +712,7 @@ void Open62541AsyncBackend::deleteReference(const QOpcUaDeleteReferenceItem &ref
{
UA_DeleteReferencesRequest request;
UA_DeleteReferencesRequest_init(&request);
- UaDeleter<UA_DeleteReferencesRequest> requestDeleter(&request, UA_DeleteReferencesRequest_deleteMembers);
+ UaDeleter<UA_DeleteReferencesRequest> requestDeleter(&request, UA_DeleteReferencesRequest_clear);
request.referencesToDeleteSize = 1;
request.referencesToDelete = UA_DeleteReferencesItem_new();
@@ -810,10 +810,6 @@ void Open62541AsyncBackend::clientStateCallback(UA_Client *client,
// UA_Client_disconnect() must be called from outside this callback or open62541 will crash
backend->m_disconnectAfterStateChangeTimer.start();
-
- // Use a queued connection to make sure the subscription is not deleted if the callback was triggered
- // inside of one of its methods.
- QMetaObject::invokeMethod(backend, "cleanupSubscriptions", Qt::QueuedConnection);
}
void Open62541AsyncBackend::inactivityCallback(UA_Client *client)
@@ -875,7 +871,7 @@ void Open62541AsyncBackend::connectToEndpoint(const QOpcUaEndpointDescription &e
return;
}
- UaDeleter<UA_ByteString> clientCertDeleter(&localCertificate, &UA_ByteString_deleteMembers);
+ UaDeleter<UA_ByteString> clientCertDeleter(&localCertificate, &UA_ByteString_clear);
success = loadFileToByteString(pkiConfig.privateKeyFile(), &privateKey);
@@ -887,7 +883,7 @@ void Open62541AsyncBackend::connectToEndpoint(const QOpcUaEndpointDescription &e
return;
}
- UaDeleter<UA_ByteString> privateKeyDeleter(&privateKey, &UA_ByteString_deleteMembers);
+ UaDeleter<UA_ByteString> privateKeyDeleter(&privateKey, &UA_ByteString_clear);
success = loadAllFilesInDirectory(pkiConfig.trustListDirectory(), &trustList, &trustListSize);
diff --git a/src/plugins/opcua/open62541/qopen62541client.cpp b/src/plugins/opcua/open62541/qopen62541client.cpp
index cecd9a4..d3e8863 100644
--- a/src/plugins/opcua/open62541/qopen62541client.cpp
+++ b/src/plugins/opcua/open62541/qopen62541client.cpp
@@ -163,6 +163,7 @@ QStringList QOpen62541Client::supportedSecurityPolicies() const
, "http://opcfoundation.org/UA/SecurityPolicy#Basic128Rsa15"
, "http://opcfoundation.org/UA/SecurityPolicy#Basic256"
, "http://opcfoundation.org/UA/SecurityPolicy#Basic256Sha256"
+ , "http://opcfoundation.org/UA/SecurityPolicy#Aes128_Sha256_RsaOaep"
#endif
};
}
diff --git a/src/plugins/opcua/open62541/qopen62541node.cpp b/src/plugins/opcua/open62541/qopen62541node.cpp
index 9885959..cbfba03 100644
--- a/src/plugins/opcua/open62541/qopen62541node.cpp
+++ b/src/plugins/opcua/open62541/qopen62541node.cpp
@@ -29,7 +29,7 @@ QOpen62541Node::~QOpen62541Node()
if (m_client)
m_client->unregisterNode(this);
- UA_NodeId_deleteMembers(&m_nodeId);
+ UA_NodeId_clear(&m_nodeId);
}
bool QOpen62541Node::readAttributes(QOpcUa::NodeAttributes attr, const QString &indexRange)
diff --git a/src/plugins/opcua/open62541/qopen62541subscription.cpp b/src/plugins/opcua/open62541/qopen62541subscription.cpp
index 610596c..15fccb0 100644
--- a/src/plugins/opcua/open62541/qopen62541subscription.cpp
+++ b/src/plugins/opcua/open62541/qopen62541subscription.cpp
@@ -146,13 +146,13 @@ void QOpen62541Subscription::modifyMonitoring(quint64 handle, QOpcUa::NodeAttrib
UA_SetPublishingModeRequest req;
UA_SetPublishingModeRequest_init(&req);
- UaDeleter<UA_SetPublishingModeRequest> requestDeleter(&req, UA_SetPublishingModeRequest_deleteMembers);
+ UaDeleter<UA_SetPublishingModeRequest> requestDeleter(&req, UA_SetPublishingModeRequest_clear);
req.publishingEnabled = value.toBool();
req.subscriptionIdsSize = 1;
req.subscriptionIds = UA_UInt32_new();
*req.subscriptionIds = m_subscriptionId;
UA_SetPublishingModeResponse res = UA_Client_Subscriptions_setPublishingMode(m_backend->m_uaclient, req);
- UaDeleter<UA_SetPublishingModeResponse> responseDeleter(&res, UA_SetPublishingModeResponse_deleteMembers);
+ UaDeleter<UA_SetPublishingModeResponse> responseDeleter(&res, UA_SetPublishingModeResponse_clear);
if (res.responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
qCWarning(QT_OPCUA_PLUGINS_OPEN62541) << "Failed to set publishing mode:" << res.responseHeader.serviceResult;
@@ -181,14 +181,14 @@ void QOpen62541Subscription::modifyMonitoring(quint64 handle, QOpcUa::NodeAttrib
UA_SetMonitoringModeRequest req;
UA_SetMonitoringModeRequest_init(&req);
- UaDeleter<UA_SetMonitoringModeRequest> requestDeleter(&req, UA_SetMonitoringModeRequest_deleteMembers);
+ UaDeleter<UA_SetMonitoringModeRequest> requestDeleter(&req, UA_SetMonitoringModeRequest_clear);
req.monitoringMode = static_cast<UA_MonitoringMode>(value.value<QOpcUaMonitoringParameters::MonitoringMode>());
req.monitoredItemIdsSize = 1;
req.monitoredItemIds = UA_UInt32_new();
*req.monitoredItemIds = monItem->monitoredItemId;
req.subscriptionId = m_subscriptionId;
UA_SetMonitoringModeResponse res = UA_Client_MonitoredItems_setMonitoringMode(m_backend->m_uaclient, req);
- UaDeleter<UA_SetMonitoringModeResponse> responseDeleter(&res, UA_SetMonitoringModeResponse_deleteMembers);
+ UaDeleter<UA_SetMonitoringModeResponse> responseDeleter(&res, UA_SetMonitoringModeResponse_clear);
if (res.responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
qCWarning(QT_OPCUA_PLUGINS_OPEN62541) << "Failed to set monitoring mode:" << res.responseHeader.serviceResult;
@@ -219,7 +219,7 @@ bool QOpen62541Subscription::addAttributeMonitoredItem(quint64 handle, QOpcUa::N
{
UA_MonitoredItemCreateRequest req;
UA_MonitoredItemCreateRequest_init(&req);
- UaDeleter<UA_MonitoredItemCreateRequest> requestDeleter(&req, UA_MonitoredItemCreateRequest_deleteMembers);
+ UaDeleter<UA_MonitoredItemCreateRequest> requestDeleter(&req, UA_MonitoredItemCreateRequest_clear);
req.itemToMonitor.attributeId = QOpen62541ValueConverter::toUaAttributeId(attr);
UA_NodeId_copy(&id, &(req.itemToMonitor.nodeId));
if (settings.indexRange().size())
@@ -244,7 +244,7 @@ bool QOpen62541Subscription::addAttributeMonitoredItem(quint64 handle, QOpcUa::N
}
UA_MonitoredItemCreateResult res;
- UaDeleter<UA_MonitoredItemCreateResult> resultDeleter(&res, UA_MonitoredItemCreateResult_deleteMembers);
+ UaDeleter<UA_MonitoredItemCreateResult> resultDeleter(&res, UA_MonitoredItemCreateResult_clear);
if (attr == QOpcUa::NodeAttribute::EventNotifier && settings.filter().canConvert<QOpcUaMonitoringParameters::EventFilter>())
res = UA_Client_MonitoredItems_createEvent(m_backend->m_uaclient, m_subscriptionId,
@@ -436,7 +436,7 @@ void QOpen62541Subscription::createEventFilter(const QOpcUaMonitoringParameters:
convertSelectClause(filter, &uaFilter->selectClauses, &uaFilter->selectClausesSize);
if (!convertWhereClause(filter, &uaFilter->whereClause))
- UA_ExtensionObject_deleteMembers(out);
+ UA_ExtensionObject_clear(out);
}
bool QOpen62541Subscription::convertSelectClause(const QOpcUaMonitoringParameters::EventFilter &filter,
@@ -458,8 +458,9 @@ bool QOpen62541Subscription::convertSelectClause(const QOpcUaMonitoringParameter
QOpen62541ValueConverter::scalarFromQt<UA_QualifiedName, QOpcUaQualifiedName>(
filter.selectClauses().at(i).browsePath().at(j), &select[i].browsePath[j]);
}
- QOpen62541ValueConverter::scalarFromQt<UA_String, QString>(filter.selectClauses().at(i).indexRange(),
- &select[i].indexRange);
+ if (!filter.selectClauses().at(i).indexRange().isEmpty())
+ QOpen62541ValueConverter::scalarFromQt<UA_String, QString>(filter.selectClauses().at(i).indexRange(),
+ &select[i].indexRange);
select[i].attributeId = QOpen62541ValueConverter::toUaAttributeId(filter.selectClauses().at(i).attributeId());
}
@@ -548,7 +549,7 @@ bool QOpen62541Subscription::convertWhereClause(const QOpcUaMonitoringParameters
} else {
qCWarning(QT_OPCUA_PLUGINS_OPEN62541) << "Unknown filter operand type for event filter" <<
filter.whereClause().at(i).filterOperands().at(j).typeName();
- UA_ContentFilter_deleteMembers(result);
+ UA_ContentFilter_clear(result);
return false;
}
}
@@ -703,7 +704,7 @@ bool QOpen62541Subscription::modifyMonitoredItemParameters(quint64 nodeHandle, Q
UA_ModifyMonitoredItemsRequest req;
UA_ModifyMonitoredItemsRequest_init(&req);
- UaDeleter<UA_ModifyMonitoredItemsRequest> requestDeleter(&req, UA_ModifyMonitoredItemsRequest_deleteMembers);
+ UaDeleter<UA_ModifyMonitoredItemsRequest> requestDeleter(&req, UA_ModifyMonitoredItemsRequest_clear);
req.subscriptionId = m_subscriptionId;
req.itemsToModifySize = 1;
req.itemsToModify = UA_MonitoredItemModifyRequest_new();
@@ -780,7 +781,7 @@ bool QOpen62541Subscription::modifyMonitoredItemParameters(quint64 nodeHandle, Q
UA_ModifyMonitoredItemsResponse res = UA_Client_MonitoredItems_modify(m_backend->m_uaclient, req);
UaDeleter<UA_ModifyMonitoredItemsResponse> responseDeleter(
- &res, UA_ModifyMonitoredItemsResponse_deleteMembers);
+ &res, UA_ModifyMonitoredItemsResponse_clear);
if (res.responseHeader.serviceResult != UA_STATUSCODE_GOOD || res.results[0].statusCode != UA_STATUSCODE_GOOD) {
p.setStatusCode(static_cast<QOpcUa::UaStatusCode>(res.responseHeader.serviceResult == UA_STATUSCODE_GOOD ? res.results[0].statusCode : res.responseHeader.serviceResult));
diff --git a/src/plugins/opcua/open62541/qopen62541valueconverter.cpp b/src/plugins/opcua/open62541/qopen62541valueconverter.cpp
index 5a8562c..61a504a 100644
--- a/src/plugins/opcua/open62541/qopen62541valueconverter.cpp
+++ b/src/plugins/opcua/open62541/qopen62541valueconverter.cpp
@@ -124,69 +124,67 @@ QVariant toQVariant(const UA_Variant &value)
return QVariant();
}
- switch (value.type->typeIndex) {
- case UA_TYPES_BOOLEAN:
+ if (value.type == &UA_TYPES[UA_TYPES_BOOLEAN])
return arrayToQVariant<bool, UA_Boolean>(value, QMetaType::Bool);
- case UA_TYPES_SBYTE:
+ else if (value.type == &UA_TYPES[UA_TYPES_SBYTE])
return arrayToQVariant<signed char, UA_SByte>(value, QMetaType::SChar);
- case UA_TYPES_BYTE:
+ else if (value.type == &UA_TYPES[UA_TYPES_BYTE])
return arrayToQVariant<uchar, UA_Byte>(value, QMetaType::UChar);
- case UA_TYPES_INT16:
+ else if (value.type == &UA_TYPES[UA_TYPES_INT16])
return arrayToQVariant<qint16, UA_Int16>(value, QMetaType::Short);
- case UA_TYPES_UINT16:
+ else if (value.type == &UA_TYPES[UA_TYPES_UINT16])
return arrayToQVariant<quint16, UA_UInt16>(value, QMetaType::UShort);
- case UA_TYPES_INT32:
+ else if (value.type == &UA_TYPES[UA_TYPES_INT32])
return arrayToQVariant<qint32, UA_Int32>(value, QMetaType::Int);
- case UA_TYPES_UINT32:
+ else if (value.type == &UA_TYPES[UA_TYPES_UINT32])
return arrayToQVariant<quint32, UA_UInt32>(value, QMetaType::UInt);
- case UA_TYPES_INT64:
+ else if (value.type == &UA_TYPES[UA_TYPES_INT64])
return arrayToQVariant<int64_t, UA_Int64>(value, QMetaType::LongLong);
- case UA_TYPES_UINT64:
+ else if (value.type == &UA_TYPES[UA_TYPES_UINT64])
return arrayToQVariant<uint64_t, UA_UInt64>(value, QMetaType::ULongLong);
- case UA_TYPES_FLOAT:
+ else if (value.type == &UA_TYPES[UA_TYPES_FLOAT])
return arrayToQVariant<float, UA_Float>(value, QMetaType::Float);
- case UA_TYPES_DOUBLE:
+ else if (value.type == &UA_TYPES[UA_TYPES_DOUBLE])
return arrayToQVariant<double, UA_Double>(value, QMetaType::Double);
- case UA_TYPES_STRING:
+ else if (value.type == &UA_TYPES[UA_TYPES_STRING])
return arrayToQVariant<QString, UA_String>(value, QMetaType::QString);
- case UA_TYPES_BYTESTRING:
+ else if (value.type == &UA_TYPES[UA_TYPES_BYTESTRING])
return arrayToQVariant<QByteArray, UA_ByteString>(value, QMetaType::QByteArray);
- case UA_TYPES_LOCALIZEDTEXT:
+ else if (value.type == &UA_TYPES[UA_TYPES_LOCALIZEDTEXT])
return arrayToQVariant<QOpcUaLocalizedText, UA_LocalizedText>(value);
- case UA_TYPES_NODEID:
+ else if (value.type == &UA_TYPES[UA_TYPES_NODEID])
return arrayToQVariant<QString, UA_NodeId>(value, QMetaType::QString);
- case UA_TYPES_DATETIME:
+ else if (value.type == &UA_TYPES[UA_TYPES_DATETIME])
return arrayToQVariant<QDateTime, UA_DateTime>(value, QMetaType::QDateTime);
- case UA_TYPES_GUID:
+ else if (value.type == &UA_TYPES[UA_TYPES_GUID])
return arrayToQVariant<QUuid, UA_Guid>(value, QMetaType::QUuid);
- case UA_TYPES_XMLELEMENT:
+ else if (value.type == &UA_TYPES[UA_TYPES_XMLELEMENT])
return arrayToQVariant<QString, UA_XmlElement>(value, QMetaType::QString);
- case UA_TYPES_QUALIFIEDNAME:
+ else if (value.type == &UA_TYPES[UA_TYPES_QUALIFIEDNAME])
return arrayToQVariant<QOpcUaQualifiedName, UA_QualifiedName>(value);
- case UA_TYPES_STATUSCODE:
+ else if (value.type == &UA_TYPES[UA_TYPES_STATUSCODE])
return arrayToQVariant<QOpcUa::UaStatusCode, UA_StatusCode>(value, QMetaType::UInt);
- case UA_TYPES_EXTENSIONOBJECT:
+ else if (value.type == &UA_TYPES[UA_TYPES_EXTENSIONOBJECT])
return arrayToQVariant<QVariant, UA_ExtensionObject>(value);
- case UA_TYPES_EXPANDEDNODEID:
+ else if (value.type == &UA_TYPES[UA_TYPES_EXPANDEDNODEID])
return arrayToQVariant<QOpcUaExpandedNodeId, UA_ExpandedNodeId>(value);
- case UA_TYPES_ARGUMENT:
+ else if (value.type == &UA_TYPES[UA_TYPES_ARGUMENT])
return arrayToQVariant<QOpcUaArgument, UA_Argument>(value);
- case UA_TYPES_RANGE:
+ else if (value.type == &UA_TYPES[UA_TYPES_RANGE])
return arrayToQVariant<QOpcUaRange, UA_Range>(value);
- case UA_TYPES_EUINFORMATION:
+ else if (value.type == &UA_TYPES[UA_TYPES_EUINFORMATION])
return arrayToQVariant<QOpcUaEUInformation, UA_EUInformation>(value);
- case UA_TYPES_AXISINFORMATION:
+ else if (value.type == &UA_TYPES[UA_TYPES_AXISINFORMATION])
return arrayToQVariant<QOpcUaAxisInformation, UA_AxisInformation>(value);
- case UA_TYPES_COMPLEXNUMBERTYPE:
+ else if (value.type == &UA_TYPES[UA_TYPES_COMPLEXNUMBERTYPE])
return arrayToQVariant<QOpcUaComplexNumber, UA_ComplexNumberType>(value);
- case UA_TYPES_DOUBLECOMPLEXNUMBERTYPE:
+ else if (value.type == &UA_TYPES[UA_TYPES_DOUBLECOMPLEXNUMBERTYPE])
return arrayToQVariant<QOpcUaDoubleComplexNumber, UA_DoubleComplexNumberType>(value);
- case UA_TYPES_XVTYPE:
+ else if (value.type == &UA_TYPES[UA_TYPES_XVTYPE])
return arrayToQVariant<QOpcUaXValue, UA_XVType>(value);
- default:
- qCWarning(QT_OPCUA_PLUGINS_OPEN62541) << "Variant conversion from Open62541 for typeName" << value.type->typeName << " not implemented";
- return QVariant();
- }
+
+ qCWarning(QT_OPCUA_PLUGINS_OPEN62541) << "Variant conversion from Open62541 for typeName" << value.type->typeName << " not implemented";
+ return QVariant();
}
const UA_DataType *toDataType(QOpcUa::Types valueType)
@@ -672,7 +670,7 @@ void scalarFromQt<UA_ExtensionObject, QOpcUaExtensionObject>(const QOpcUaExtensi
{
QByteArray temp = obj.encodedBody();
UA_NodeId encodingId = Open62541Utils::nodeIdFromQString(obj.encodingTypeId());
- UaDeleter<UA_NodeId> nodeIdDeleter(&encodingId, UA_NodeId_deleteMembers);
+ UaDeleter<UA_NodeId> nodeIdDeleter(&encodingId, UA_NodeId_clear);
createExtensionObject(temp, encodingId, ptr, obj.encoding());
}
diff --git a/tests/auto/declarative/AbsoluteNodeTest.qml b/tests/auto/declarative/AbsoluteNodeTest.qml
index d18dbef..a092234 100644
--- a/tests/auto/declarative/AbsoluteNodeTest.qml
+++ b/tests/auto/declarative/AbsoluteNodeTest.qml
@@ -401,7 +401,7 @@ Item {
node12.value = 30;
node12ValueSpy.wait();
- compare(node12ValueSpy.count, 1);
+ verify(node12ValueSpy.count > 0);
compare(node12.value, 30);
compare(node12.value, 30.0);
diff --git a/tests/auto/declarative/DiscoveryTest.qml b/tests/auto/declarative/DiscoveryTest.qml
index 4f73ad6..09b75db 100644
--- a/tests/auto/declarative/DiscoveryTest.qml
+++ b/tests/auto/declarative/DiscoveryTest.qml
@@ -122,7 +122,7 @@ Item {
tryVerify(function() { return myEndpoints1.count > 0;});
if (SERVER_SUPPORTS_SECURITY)
- compare(myEndpoints1.count, 7);
+ compare(myEndpoints1.count, 9);
else
compare(myEndpoints1.count, 1);
verify(myEndpoints1.at(0).endpointUrl.startsWith("opc.tcp://"));
@@ -229,7 +229,7 @@ Item {
compare(endpointsStatusSpy2.count, 2);
compare(endpointsChangedSpy2.count, 2);
if (SERVER_SUPPORTS_SECURITY)
- compare(myEndpoints2.count, 7);
+ compare(myEndpoints2.count, 9);
else
compare(myEndpoints2.count, 1);
verify(myEndpoints2.at(0).endpointUrl.startsWith("opc.tcp://"));
diff --git a/tests/auto/declarative/SecurityTest.qml b/tests/auto/declarative/SecurityTest.qml
index bcdb20b..76b1500 100644
--- a/tests/auto/declarative/SecurityTest.qml
+++ b/tests/auto/declarative/SecurityTest.qml
@@ -33,7 +33,7 @@ Item {
compare(connection2.supportedUserTokenTypes.length, 3);
} else if (backendName === "open62541") {
if (SERVER_SUPPORTS_SECURITY)
- compare(connection2.supportedSecurityPolicies.length, 4);
+ compare(connection2.supportedSecurityPolicies.length, 5);
else
compare(connection2.supportedSecurityPolicies.length, 1);
compare(connection2.supportedUserTokenTypes.length, 2);
diff --git a/tests/auto/qopcuaclient/tst_client.cpp b/tests/auto/qopcuaclient/tst_client.cpp
index f631f35..7eee632 100644
--- a/tests/auto/qopcuaclient/tst_client.cpp
+++ b/tests/auto/qopcuaclient/tst_client.cpp
@@ -2918,17 +2918,6 @@ void Tst_QOpcUaClient::subscriptionDataChangeFilter()
QVERIFY(monitoringModifiedSpy.at(0).at(1).value<QOpcUaMonitoringParameters::Parameters>() & QOpcUaMonitoringParameters::Parameter::Filter);
QCOMPARE(monitoringModifiedSpy.at(0).at(2).value<QOpcUa::UaStatusCode>(), QOpcUa::UaStatusCode::Good);
- // Since v1.0, the server sends a new initial data change after modifying a monitored item
- if (dataChangeSpy.isEmpty())
- dataChangeSpy.wait(signalSpyTimeout);
- QVERIFY(!dataChangeSpy.isEmpty());
- dataChangeSpy.clear();
-
- if (attributeUpdatedSpy.isEmpty())
- attributeUpdatedSpy.wait(signalSpyTimeout);
- QVERIFY(!attributeUpdatedSpy.isEmpty());
- attributeUpdatedSpy.clear();
-
WRITE_VALUE_ATTRIBUTE(doubleWriteNode, 2.0, QOpcUa::Types::Double);
dataChangeSpy.wait(signalSpyTimeout);
@@ -3190,7 +3179,7 @@ void Tst_QOpcUaClient::checkMonitoredItemCleanup()
serverNode->callMethod(QOpcUa::namespace0Id(QOpcUa::NodeIds::Namespace0::Server_GetMonitoredItems), parameter);
methodSpy.wait(signalSpyTimeout);
QCOMPARE(methodSpy.size(), 1);
- QCOMPARE(methodSpy.at(0).at(2).value<QOpcUa::UaStatusCode>(), QOpcUa::UaStatusCode::BadNoMatch);
+ QCOMPARE(methodSpy.at(0).at(2).value<QOpcUa::UaStatusCode>(), QOpcUa::UaStatusCode::BadSubscriptionIdInvalid);
}
void Tst_QOpcUaClient::checkAttributeUpdated()
@@ -4258,6 +4247,7 @@ void Tst_QOpcUaClient::connectionLost()
// open62541 returns a different status code depending on when after the disconnect the request is made
if (opcuaClient->backend() == QStringLiteral("open62541"))
QVERIFY(stringNode->attributeError(QOpcUa::NodeAttribute::BrowseName) == QOpcUa::UaStatusCode::BadInternalError ||
+ stringNode->attributeError(QOpcUa::NodeAttribute::BrowseName) == QOpcUa::UaStatusCode::BadSecureChannelClosed ||
stringNode->attributeError(QOpcUa::NodeAttribute::BrowseName) == QOpcUa::UaStatusCode::BadSessionClosed ||
stringNode->attributeError(QOpcUa::NodeAttribute::BrowseName) == QOpcUa::UaStatusCode::BadConnectionClosed ||
stringNode->attributeError(QOpcUa::NodeAttribute::BrowseName) == QOpcUa::UaStatusCode::BadServerNotConnected);
diff --git a/tests/open62541-testserver/CMakeLists.txt b/tests/open62541-testserver/CMakeLists.txt
index 23e9d3b..e9a253c 100644
--- a/tests/open62541-testserver/CMakeLists.txt
+++ b/tests/open62541-testserver/CMakeLists.txt
@@ -84,7 +84,6 @@ endif()
qt_internal_extend_target(open62541-testserver CONDITION QT_FEATURE_open62541_security AND WrapOpenSSL_FOUND AND QT_FEATURE_open62541 AND NOT QT_FEATURE_system_open62541
DEFINES
- UA_ENABLE_ENCRYPTION
UA_ENABLE_ENCRYPTION_OPENSSL
LIBRARIES
WrapOpenSSL::WrapOpenSSL
@@ -119,7 +118,7 @@ if (QT_FEATURE_open62541 AND NOT QT_FEATURE_system_open62541)
set_source_files_properties(../../src/3rdparty/open62541/open62541.c PROPERTIES LANGUAGE CXX)
set_source_files_properties(../../src/3rdparty/open62541/open62541.c PROPERTIES
COMPILE_OPTIONS
- "/Zc:strictStrings-;/permissive;/wd2362")
+ "/Zc:strictStrings-;/permissive;/wd4200")
endif()
endif()
# special case end
diff --git a/tests/open62541-testserver/testserver.cpp b/tests/open62541-testserver/testserver.cpp
index f36ff96..96ad7b9 100644
--- a/tests/open62541-testserver/testserver.cpp
+++ b/tests/open62541-testserver/testserver.cpp
@@ -68,7 +68,7 @@ static UA_ByteString loadFile(const QString &filePath) {
return fileContents;
if (file.read(reinterpret_cast<char*>(fileContents.data), fileContents.length) != static_cast<qint64>(fileContents.length)) {
- UA_ByteString_deleteMembers(&fileContents);
+ UA_ByteString_clear(&fileContents);
fileContents.length = 0;
return fileContents;
}
@@ -81,9 +81,9 @@ bool TestServer::createSecureServerConfig(UA_ServerConfig *config)
const QString privateKeyFilePath = QLatin1String(":/pki/own/private/open62541-testserver.der");
UA_ByteString certificate = loadFile(certificateFilePath);
- UaDeleter<UA_ByteString> certificateDeleter(&certificate, UA_ByteString_deleteMembers);
+ UaDeleter<UA_ByteString> certificateDeleter(&certificate, UA_ByteString_clear);
UA_ByteString privateKey = loadFile(privateKeyFilePath);
- UaDeleter<UA_ByteString> privateKeyDeleter(&privateKey, UA_ByteString_deleteMembers);
+ UaDeleter<UA_ByteString> privateKeyDeleter(&privateKey, UA_ByteString_clear);
if (certificate.length == 0) {
UA_LOG_WARNING(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND,
@@ -166,7 +166,7 @@ bool TestServer::createSecureServerConfig(UA_ServerConfig *config)
certificateDeleter.release();
privateKeyDeleter.release();
- result = UA_AccessControl_default(config, true,
+ result = UA_AccessControl_default(config, true, nullptr,
&config->securityPolicies[0].policyUri,
usernamePasswordsSize, usernamePasswords);
@@ -243,9 +243,9 @@ UA_NodeId TestServer::addFolder(const QString &nodeString, const QString &displa
nullptr,
&resultNode);
- UA_QualifiedName_deleteMembers(&nodeBrowseName);
- UA_NodeId_deleteMembers(&requestedNodeId);
- UA_ObjectAttributes_deleteMembers(&oAttr);
+ UA_QualifiedName_clear(&nodeBrowseName);
+ UA_NodeId_clear(&requestedNodeId);
+ UA_ObjectAttributes_clear(&oAttr);
if (result != UA_STATUSCODE_GOOD) {
qWarning() << "Could not add folder:" << nodeString << " :" << result;
@@ -274,8 +274,8 @@ UA_NodeId TestServer::addObject(const UA_NodeId &parentFolder, int namespaceInde
nullptr,
&resultNode);
- UA_QualifiedName_deleteMembers(&nodeBrowseName);
- UA_ObjectAttributes_deleteMembers(&oAttr);
+ UA_QualifiedName_clear(&nodeBrowseName);
+ UA_ObjectAttributes_clear(&oAttr);
if (result != UA_STATUSCODE_GOOD) {
qWarning() << "Could not add object to folder:" << result;
@@ -315,8 +315,8 @@ UA_NodeId TestServer::addVariableWithWriteMask(const UA_NodeId &folder, const QS
&resultId);
- UA_NodeId_deleteMembers(&variableNodeId);
- UA_VariableAttributes_deleteMembers(&attr);
+ UA_NodeId_clear(&variableNodeId);
+ UA_VariableAttributes_clear(&attr);
if (result != UA_STATUSCODE_GOOD) {
qWarning() << "Could not add variable:" << result;
@@ -366,7 +366,7 @@ UA_NodeId TestServer::addVariable(const UA_NodeId &folder, const QString &variab
nullptr,
&resultId);
- // Prevent deletion of the QList's value by UA_VariableAttribute_deleteMembers
+ // Prevent deletion of the QList's value by UA_VariableAttribute_clear
attr.arrayDimensions = nullptr;
attr.arrayDimensionsSize = 0;
@@ -382,8 +382,8 @@ UA_NodeId TestServer::addVariable(const UA_NodeId &folder, const QString &variab
}
}
- UA_NodeId_deleteMembers(&variableNodeId);
- UA_VariableAttributes_deleteMembers(&attr);
+ UA_NodeId_clear(&variableNodeId);
+ UA_VariableAttributes_clear(&attr);
if (result != UA_STATUSCODE_GOOD) {
qWarning() << "Could not add variable:" << result << "for node" << variableNode;
@@ -427,8 +427,8 @@ UA_NodeId TestServer::addEmptyArrayVariable(const UA_NodeId &folder, const QStri
nullptr,
&resultId);
- UA_NodeId_deleteMembers(&variableNodeId);
- UA_VariableAttributes_deleteMembers(&attr);
+ UA_NodeId_clear(&variableNodeId);
+ UA_VariableAttributes_clear(&attr);
if (result != UA_STATUSCODE_GOOD) {
qWarning() << "Could not add empty array variable:" << result;
@@ -507,12 +507,12 @@ UA_NodeId TestServer::addMultiplyMethod(const UA_NodeId &folder, const QString &
1, &outputArgument,
nullptr, &resultId);
- UA_QualifiedName_deleteMembers(&nodeBrowseName);
- UA_NodeId_deleteMembers(&methodNodeId);
- UA_MethodAttributes_deleteMembers(&attr);
- UA_Argument_deleteMembers(&inputArguments[0]);
- UA_Argument_deleteMembers(&inputArguments[1]);
- UA_Argument_deleteMembers(&outputArgument);
+ UA_QualifiedName_clear(&nodeBrowseName);
+ UA_NodeId_clear(&methodNodeId);
+ UA_MethodAttributes_clear(&attr);
+ UA_Argument_clear(&inputArguments[0]);
+ UA_Argument_clear(&inputArguments[1]);
+ UA_Argument_clear(&outputArgument);
if (result != UA_STATUSCODE_GOOD) {
qWarning() << "Could not add variable:" << result;
@@ -598,13 +598,13 @@ UA_NodeId TestServer::addMultipleOutputArgumentsMethod(const UA_NodeId &folder,
2, outputArgument,
nullptr, &resultId);
- UA_QualifiedName_deleteMembers(&nodeBrowseName);
- UA_NodeId_deleteMembers(&methodNodeId);
- UA_MethodAttributes_deleteMembers(&attr);
- UA_Argument_deleteMembers(&inputArguments[0]);
- UA_Argument_deleteMembers(&inputArguments[1]);
- UA_Argument_deleteMembers(&outputArgument[0]);
- UA_Argument_deleteMembers(&outputArgument[1]);
+ UA_QualifiedName_clear(&nodeBrowseName);
+ UA_NodeId_clear(&methodNodeId);
+ UA_MethodAttributes_clear(&attr);
+ UA_Argument_clear(&inputArguments[0]);
+ UA_Argument_clear(&inputArguments[1]);
+ UA_Argument_clear(&outputArgument[0]);
+ UA_Argument_clear(&outputArgument[1]);
if (result != UA_STATUSCODE_GOOD) {
qWarning() << "Could not add variable:" << result;
@@ -650,11 +650,11 @@ UA_NodeId TestServer::addAddNamespaceMethod(const UA_NodeId &folder, const QStri
1, &outputArgument,
nullptr, &resultId);
- UA_QualifiedName_deleteMembers(&nodeBrowseName);
- UA_NodeId_deleteMembers(&methodNodeId);
- UA_MethodAttributes_deleteMembers(&attr);
- UA_Argument_deleteMembers(&inputArguments[0]);
- UA_Argument_deleteMembers(&outputArgument);
+ UA_QualifiedName_clear(&nodeBrowseName);
+ UA_NodeId_clear(&methodNodeId);
+ UA_MethodAttributes_clear(&attr);
+ UA_Argument_clear(&inputArguments[0]);
+ UA_Argument_clear(&outputArgument);
if (result != UA_STATUSCODE_GOOD) {
qWarning() << "Could not add method:" << result;