summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/open62541/open62541.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/open62541/open62541.c')
-rw-r--r--src/3rdparty/open62541/open62541.c59419
1 files changed, 33978 insertions, 25441 deletions
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;
}